Move it to a structure. Make all the modifiers methods. Change all
callers of those methods to pass the structure. This makes the stuck
object handling free of direct access to global game data.
Commit a833d73d44 added the SDL_mixer backend for Rebirth sound. That
commit set the length of the converted sound equal to the size of the
buffer that SDL requested as a work area. No one ever touched that
logic, until now. In SDL1, that choice worked fine. In SDL2, this
causes garbage to play after the sound, because SDL2 considers the
buffer to be defined only up to the length returned in
`SDL_AudioCVT::cvt_len`. Bytes beyond that length are undefined[1], and
in practice contain garbage. Fix the noise by setting the sound length
equal to the length returned by SDL2, so that the undefined bytes are
not treated as sound. SDL1 also maintains this length value, so no
version-specific logic is required.
[1]: https://wiki.libsdl.org/SDL_ConvertAudio
Reported-by: heftig <https://github.com/dxx-rebirth/dxx-rebirth/issues/396>
This commit enables Rebirth to build with SDL2, but the result is not
perfect.
- SDL2 removed some sticky key support. Rebirth may behave differently
now in this area.
- SDL2 removed some key-repeat related support. Rebirth may behave
differently now in this area.
- SDL2 gained the ability to make a window fullscreen by sizing it to
the desktop instead of by changing the desktop resolution. Rebirth
uses this, and it mostly works.
- Resizing while in the automap does not notify the automap code, so
the view is wrong until the player switches out of automap mode and
back in.
- SDL2 changed how to enumerate available resolutions. Since
fitting the window to the desktop is generally more useful than
fitting the desktop to the window, I chose to drop support for
enumerating resolutions instead of porting to the new API. Users can
now enter an arbitrary window dimension and Rebirth will make an
attempt to use it.
- It might be useful to cap the window dimension at the desktop
dimension, but that is not done yet.
- Entering fullscreen mode through the Controls->Graphics submenu
failed to notify the relevant subsystems, causing the rendered
content not to rescale. For now, compile out the option to toggle
full screen through that menu. Toggling through Alt+Enter works
properly.
Despite these quirks, this is a substantial improvement over the prior
commit, where SDL2 cannot be used at all. The remaining issues can be
resolved in future work.
References: <https://github.com/dxx-rebirth/dxx-rebirth/issues/82>
User Nemesis reported an unspecified crash, but never responded to
inquiries to provide more data. Users Tourmeister and Buff Skeleton
reported a fatal exception thrown while paging in a vclip, with initial
triggering conditions matching the report from Nemesis. Both
Tourmeister and Buff Skeleton are using v1.0 Descent 2 data. No one
with more recent data has reported a problem.
Add a try { ... } catch { ... } block to trap the partial_range
exception, log it, and then ignore paging in that vclip. This should
approximate what 0.58.1 did, assuming that the crash is due to a
negative `num_frames`. If the crash is due to a large positive
`num_frames`, this change will still prevent the previously reported
crash, but may only move the crash elsewhere. Various other subsystems
react badly to using a vclip that has not been paged in.
This change is tested not to break an otherwise working game. It is not
tested to confirm that it produces a working game for users who
experienced a crash without it.
Reported-by: Tourmeister <https://forum.dxx-rebirth.com/showthread.php?tid=943&pid=12159#pid12159>
Reported-by: Buff Skeleton <https://forum.dxx-rebirth.com/showthread.php?tid=943&pid=12290#pid12290>
References: <https://github.com/dxx-rebirth/dxx-rebirth/issues/371>
Currently, DXX_USE_SDL_REDBOOK_AUDIO is an alias for !SDL2. However,
this patch enables interested users to readily patch out Redbook even
for SDL1.
References: <https://github.com/dxx-rebirth/dxx-rebirth/issues/82>
The player appearance sound was tied to the player appearance vclip,
but this is wrong because the vclip has a shorter lifetime than the
sound. This mistake was previously hidden by the hack that caused
non-permanent sounds to be routed off to a separate queue that lost the
association between object and sound. Commit 4a98e79 eliminated that
hack because it complicated the work of that commit. However, without
the hack, object sound effects cannot outlive their host object.
Fix this by binding the sound to the position of the appearance effect,
not to the appearance object. This works since the appearance effect
cannot move, so there was no value to binding the sound to the object.
This solution could not be used for objects that move and terminate
before their associated sound effect.
Reported-by: Ryusei117 <https://github.com/dxx-rebirth/dxx-rebirth/issues/88#issuecomment-390054173>
Fixes: 4a98e796ab ("Prevent stacking weapon rotation sounds")
User jcotton42 suggested copying a D2X-XL feature: preserving the
directory structure of the user's missions area when showing a New Game
dialog. This was substantially more trouble than it should have been,
but the result is good.
Previously, the dialog presented all missions at any depth below the
starting point, and sorted them as if they were all in the root
directory.
Now:
- Empty directories are hidden entirely. There is nothing for the user
to do in them, so there is no point showing them.
- A directory with exactly one entry has that entry promoted into the
parent, since there is no ambiguity about what the user would want.
If the parent in turn has only that one promoted element when the scan
of the parent finishes, then the element can be promoted up again.
This continues until the root is reached or until a level has more
than one entry. For this purpose, both missions and directories count
as entries.
- Directory entries are decorated to inform the user how many
immediate subdirectories are present, how many missions are present
immediately in the directory, and how many missions total are present,
counting all subdirectories. If there are zero immediate
subdirectories, then the directory count is not shown. For this
purpose, directories that were hidden due to a lack of missions are
not counted.
- Sub-dialog boxes for inner directories use a title that reminds the
user of the path so far, and recaps the directory/mission statistics.
- On entry to the New Game dialog, if the last played mission is in a
sub-dialog, appropriate sub-dialogs are opened so that the last played
mission can be pre-selected.
Currently, there is no in-game override to return to the prior rollup
rules.
Requested-by: jcotton42 <https://github.com/dxx-rebirth/dxx-rebirth/issues/392>
Even when empty and default-constructible, const members must be
explicitly constructed. Add a default constructor to do this.
Fixes: 893e8cde06 ("Combine hud gauge parameters")
Using sizeof(con_printf A) was a trick to avoid code generation, but it
interacts badly with gcc-6 and the other macros that con_printf
produces. On >=gcc-6, `DXX_ALWAYS_ERROR_FUNCTION` is a complicated hack
to work around undesirable changes in `__builtin_constant_p`. That hack
includes introducing a dummy type. gcc-6 rejects declaring a type
inside a statement expression inside a sizeof. gcc-7 permits this, so
it went unnoticed.
This particular usage was to prevent future regressions in calls that
had been broken for years without anyone noticing. As such, reverting
to not checking those calls is unlikely to matter.
Reported-by: Ambaire <https://github.com/dxx-rebirth/dxx-rebirth/issues/393#issuecomment-401565872>
Fixes: 9b17450914 ("Fix up long broken glmprintf support")
gcc-5 rejects `V == V::E` where the first V is a variable of type V and
the second V is a scope specifier to indicate the member E in the type
V. gcc-7 permits this.
Fixes: 5cafec2268 ("Use enum for gauges weapon_type")
`memcpy(a, b, strlen(b));` is just a complicated way of writing
`strcpy(a, b);`, but even more dangerous since it omits the null
terminator. `strcpy` on untrusted data is always unsafe, and this data
does not appear to be checked before use. There is no need to copy the
data before using it, so switch to using it in place. This eliminates
the security problem and makes the code slightly smaller.
Fixes: 730879d733 ("Updated handling of data sent by tracker. ...")
The new tracker automatically exposes LAN games to the Internet. This
surprised one user rather badly, prompting him to think he had been
hacked. Add a first-host warning explaining the feature and asking the
user to choose whether to enable NAT hole punch.
Reported-by: Tourmeister <https://forum.dxx-rebirth.com/showthread.php?tid=943&pid=12179#pid12179>
References: <https://github.com/dxx-rebirth/dxx-rebirth/issues/372>
Fixes: 730879d733 ("... Added support for handling ACKs from tracker and Hole punching between game clients via tracker. ...")
Various functions are preprocessor-excluded by `BOTTOM_STUFF`, which has
been 0 since btb added it in a196e6d554
(October 2001). It seems unlikely that anyone will miss it.
Prior releases destroyed the control center when the kill goal timer
expired, even if no player had scored any kills. General cleanup of
kill goal quirks eliminated this odd rule, but players liked the old
rule and want it back. Restore it.
Per comment from kreator, some Apple systems now ship without a working
print screen key. It makes no sense to provide print screen support
bound to a key which does not exist. Add `screenshot=none` and activate
it on OS X to remove the unreachable screenshot support.
If the player commits suicide in Descent 2, Point_segs[-2] is accessed
because aip->hide_index = -1, aip->path_length = 0. As a spot fix,
check for underflow and skip the access if it would be out of bounds.
Prior versions of Descent had a bug that specifying `briefing=` did not
inhibit a briefing. Instead the directive was completely ignored. The
engine would then use the auto-detected briefing if one was found. This
quirk was eliminated during refactoring of the mission parsing code.
Unfortunately, some published missions relied on this bug: they ship a
briefing, but their mission file explicitly states that there is no
briefing. Players expect the briefing to play despite the mission
stating that there is none.
Reorder the logic to restore the bug that `briefing=` is ignored.
Reported-by: Calmarius <https://forum.dxx-rebirth.com/showthread.php?tid=1054>
Fixes: 6020c9c013 ("Use d_fname for DOS filenames")
When using variadic forwarding constructors
(`sconf_cxx11_inherit_constructor=force-failure`) instead of inheriting
constructors, some ternary expressions become ambiguous due to the
inability to forward the `explicit` modifier from the base class
constructor to the derived class. Add explicit type overrides to
disambiguate these expressions to the result that the compiler would
have picked on its own when using inheriting constructors.
Ill-formed levels can provoke this exception. Downgrade the error from
a fatal exception to a CON_URGENT message.
Increase the array size to 32 from D1:7, D2:20, since each element is
only an int.
Switch from an assertion on bitmask overflow to a CON_URGENT warning.
Fixes: f7f416c3cb ("Trap blown bitmap overflow")
Many gauge functions take the same parameters, and pass those parameters
on to child functions in turn. Bundle common parameters into a few
standard structures, so that adding new context does not need to involve
every function in the chain for every new context value.
If user_settings.sharepath is configured to be blank in SConstruct, omit
the C preprocessor macro SHAREPATH instead of defining it to expand to
an empty string. Adjust the C++ code that uses the macro SHAREPATH to
handle its absence:
- Clearer output in help text
- Skip adding blank SHAREPATH to the PhysFS search path.
As a nice side effect, this enables SHAREPATH on Windows, which could be
helpful for builds shipped with an installer that places game files in a
well-known location (such as "C:\Games\Descent"). Previously,
!defined(__unix__) systems did not add SHAREPATH to the PhysFS search
path, even when one was defined.
digi_play_sample_once is supposed to cancel prior instances of the
sound, but that functionality was lost in
21082c6db2. As a result, the sound can be
stacked up to the limit of the engine. Even when the functionality
existed, its implementation was wrong.
- Change these sounds to be attached to the player generating them.
- Pass the cancellation flag to other players when sending a sound.
- Send the full value of `volume`, rather than truncating it.
- Implement cancellation by killing and restarting the earlier version of a cancelled sound.
- Delete an ugly hack that prevented the patched logic from ever running.
- Fix an ancient quirk in digi_mixer that caused it to report all sounds as not playing, which then caused digi_sync_sounds to instantly cancel the new sound.
Reported-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/88>
Reported-by: ryusei117 <https://github.com/dxx-rebirth/dxx-rebirth/issues/88#issuecomment-269597361>
Fixes: 21082c6db2 ("Added own channel management to SDL_mixer sound interface since the builtin channel management of this lib cannot handle our needs; Little code cleanup")
Define global copies of the user's chosen host address, host port, and
local port. When these are non-empty, prefer them to the values from
-udp_hostaddr, -udp_hostport, and -udp_myport. When the user attempts a
connection, update the global copies from the user's data. If the user
abandons the connect dialog, do not update the globals.
Requested-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/73>
Slide left/right: A/D
Slide up/down: C/X
Accelerate/reverse: W/S
Afterburner (D2 only): Left-Shift
This produces the more FPS-typical WASD layout for
forward/left/back/right movement, and maps the crouch/stand bindings to
slide up/down. This ticket sat for longer than it should have (though
it never missed a release). Several competing designs were suggested,
but only one could be made active. After consideration, I used my own
bindings on the basis that, while some other bindings may be better,
every other configuration repurposed a classic weapons-fire key to
movement. Returning players who get the "new defaults" on a newly
created pilot profile might be very surprised by having their fire keys
move. Since these are only defaults, and can be rebound by the player
with a few minutes work, these defaults do not need to be perfect. They
just need to be an improvement over original Descent.
Delete unexpand-cpp-kconfig-key.py. It will likely never be needed, and
was added in the prior commit solely to have a file to recover if it
ever is needed.
Requested-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/214>
Various files included compiler-static_assert.h to use the compatibility
macros for compilers that lacked a working C++11 static_assert.
However, some source files used static_assert without this inclusion,
and no one ever reported problems. From this, assume that no one uses a
compiler which lacks C++11 static_assert. Remove the inclusions that
were only for the compatibility macro. Keep the inclusions that use the
assert_equal helper.
Materialization centers ("Matcens") have a governor to prevent
overrunning the level in robots. However, due to a logic ordering
error, multiplayer games failed to record how many robots had been
destroyed, so for the purpose of detecting whether there were currently
"too many" robots in play, the game pretended that no robots had ever
been destroyed. Therefore, once enough robots had been created to reach
the "too many" threshold, matcens stopped generating robots, regardless
of how efficiently the player(s) had been destroying robots.
Reported-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/132>
Reported-by: Sirius-TR <https://github.com/dxx-rebirth/dxx-rebirth/issues/386>
If no character matches the typed character, the loop should exit when
`lb->citem == cc`, which should happen after every entry is visited
once. However, if no item is selected, `lb->citem == -1`, and `cc` is
never `-1`, so the exit path never triggers. Rewrite the loop to be
bounded by number of steps, rather than bounded by returning to a
particular offset. This also protects against undefined behavior if the
menu had zero elements.
[Kp: as discussed in pull #377
<https://github.com/dxx-rebirth/dxx-rebirth/pull/377>, the previous
implementation requested a parameter combination not permitted by
OpenGL. At best, this error was silently ignored. Fix the error by
falling through to a switch case statement that sets valid parameters.]
Users with disabled VSync might not expect any forced waiting on the GPU,
and the GL sync methods were intented to fix issues with VSync only,
so the new heuristic for SYNC_GL_AUTO is to enable GL sync only if
VSync is enabled, too.
Users can still request to use a specific GL sync method via the
-gl_syncmethod switch, independent of the VSync setting.
[Kp: folded `else { if () }` into `else if ()` to avoid moving
`ogl_have_ARB_sync` lines. Original change visible at
<https://github.com/dxx-rebirth/dxx-rebirth/pull/381>.]
Global `Viewer` was copied to local `viewer`, and the local should have
been used in this block. Instead, the global was incorrectly used.
gcc-5 warns for this unused variable. gcc-6 and gcc-7 incorrectly do
not warn.
Reported-by: Jayman2000 <https://github.com/dxx-rebirth/dxx-rebirth/issues/375>
Fixes: 131c1b9f4d ("Add support for PNG screenshots")
Mako88 requests, as have others in the Rebirth forum, that the FPS
indicator be placed on the right side. Moving to the right side was
quick. Moving it low, handling all the different rendering combinations
(cockpit, statusbar, fullscreen; standard vs alternate; single player vs
multiplayer), and not overlapping anything in any of them was time
consuming.
If anyone wants more changes in this area, the existing modes ought to
be revisited and unified. As is, there are pointless inconsistencies
among the modes, which makes it unnecessarily difficult to position an
element correctly.
Requested-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/122>
Commit d580328 eliminated junk whitespace in the individual line items
for joinable games. Unfortunately, this whitespace was not junk. It
was an undocumented workaround (possibly even unknowing workaround) for
a bug that undercounts the space required to show the header. Restore
the "junk" padding to force the window back to its old width.
Reported-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/374>
Fixes: d580328698 ("Combine direct_join allocations")
Mako88 reports incorrect images captured when using a screen resolution
of 1366x768. 1366 is not a multiple of 4. Debugging also shows memory
corruption at this resolution, as Mesa writes off the end of the
allocated buffer. Padding the buffer to tolerate these writes is
insufficient, as libpng then crashes with an alignment fault trying to
read unaligned data from the buffer. All these problems are eliminated
by rounding the width and height to the next multiple of 4.
Reported-by: Mako88 <https://github.com/dxx-rebirth/dxx-rebirth/issues/373>
Fixes: 131c1b9f4d ("Add support for PNG screenshots")
Ambient sound effects have always been buggy in certain topologies,
since `ambient_mark_bfs` refuses to cross its own path. Consider a
corridor:
L _ _ _ _ _ _ _ _ _ _
_ _
_ L
Where L is a lavafall emitting sound, whitespace is insignificant, _ is
a segment, * is a tagged segment, and / is a segment that should be
tagged, but is not. Let the leftmost L be a lower number segment than
the lower L. Sound propagation after the first step is:
L * * * * * _ _ _ _ _
* _
* L
After the second step, it should be:
L * * * * * * * * _ _
* *
* L
However, `ambient_mark_bfs` will stop when it hits the intersection, so
instead the result is:
L * * * * * / / / _ _
* *
* L
To further confuse the issue, emitter segments are processed in memory
order, so if the leftmost L is a higher index segment than the lower L,
the lower L will be processed first and the steps will be:
L _ * * * * * * * _ _
_ *
_ L
L * * * * * * * * _ _
/ *
/ L
Rewrite the propagation to record the travel depth remaining at each
node, and permit it to cross a segment with a lower depth remaining than
the current step. This still stops early when traversal attempts to
backtrack over itself, but permits it to visit, tag, and cross segments
that were previously visited by a different emitter.
clang rightly warns for `if (!var&1)`, which parses as `if (!(var &
1))`, which is probably not what the original author intended.
Unfortunately, the author never commented what *was* intended. The
author might have meant to reject any row with an even length (`if
(!(var & 1))`, but that seems strange in this context. Remove the `&
1`, which retains the sense of what the code has always done.
clang warns for taking the address of unaligned data, but not for taking
a reference to it. It should warn for both. The data should be fixed
not to be unaligned, but for now, this change will quiet the warning.
OS X clang warns when a variable is captured but not used. Linux gcc
does not. Remove the unused variable.
Reported-by: kreatordxx <https://github.com/dxx-rebirth/dxx-rebirth/issues/368>
Fixes: 7da64d3782 ("Add new autoselect-while-firing mode: "when firing stops"")
Packed structures cannot be passed by reference, may fail on
alignment-strict architectures, and are bad for performance even on
alignment-tolerant architectures. Using them for anything other than an
abstract layout declaration is a mistake. Remove
__attribute__((packed)).
Many predicate functions only need to return zero/nonzero, and the
callers do not care about the particular value of nonzero. Use this to
eliminate loads of explicit `1`, instead returning a nonzero value
generated by the test.
User roncli reports[1] an original game bug that prevents boss
teleportation from operating correctly if the program is not restarted
between each campaign. This is another case of a global variable being
used improperly. Reset the relevant variables when the boss is
initialized.
[1] https://github.com/dxx-rebirth/dxx-rebirth/issues/366#issuecomment-373199624
`build_colormap_good` only took `used` to clear it. Only one caller
needed it cleared. Move the clear into that caller. Remove the
parameter from all calls.
The Windows build did not explicitly include <time.h> or equivalent, but
used `time` and `gmtime`, which are only available when <time.h> is
included. Other platforms include <time.h> incidentally.
Fixes: 131c1b9f4d ("Add support for PNG screenshots")