This makes the alignment data structure `chunk` private to interp.cpp,
and allows most files to ignore whether DXX_WORDS_NEED_ALIGNMENT is
enabled, thus improving the ccache hit rate.
lengthof was added to provide the size of C arrays. C++17 std::size is
now available, and can serve the same purpose. Remove the custom
lengthof.
The generated code is the same in both cases, other than the change in
line numbers caused by removal of the #include directives.
Use an enum class to prevent implicit conversion between trigger
behavior flags and other integers. Fix up various resulting breaks,
which look like bugs:
- Descent 2 editor mode could modify trigger::flags, but used
TRIGGER_FLAG_* values, which specify the actions for a Descent 1
trigger when it executes, not the behavior properties for a trigger.
- Adding a trigger set its flags to 0, then cleared all flags except
TRIGGER_ON. Since the flags were just set to 0, the mask operation is
useless. Remove it.
- trigger_turn_all_ON cleared all flags except TRIGGER_ON. This seems
to be completely wrong. Change it to remove
trigger_behavior_flags::disabled. Descent 1 has no (working) support
for disabling triggers, so make trigger_turn_all_ON exclusive to
Descent 2.
- wall_restore_all would enable TRIGGER_ON in both games. Descent 1
never reads TRIGGER_ON. Descent 2 uses this field for trigger
behavior flags, and TRIGGER_ON is not a behavior flag.
- For Descent 1 builds, remove the modification of the field.
- For Descent 2 builds, change it to clear
trigger_behavior_flags::disabled.
Instead of parsing the button name string,
an explicit button-to-key mapping table
is now built and used.
Also fixes a few minor inconsistencies
that were introduced in c24864b1.
A new configurable joystick button binding is
introduced that opens the ingame menu, i.e. the
menu that appears when pressing the Escape key.
Fortunately, there was still enough space left
in the button binding maps for both games. The
configuration screen, however, needed to be
extended by a row to make room for the new
binding on d2x.
One known issue: When using an old player
configuration file, the menu button bindings
are initially set to J1 B1, because the unused
slots in DefaultKeySettings used to be
initialized that way. There's not much we can
do about that; the player needs to remove
these bogus assignments by hand. We can (and
do) prevent that from happening again, though,
by initializing new player files with correct
unmapped buttons.
In most menus, keyboard commands are synthesized
from controller buttons, leveraging the existing
axis-to-button translation.
Menu controls are currently fixed:
- button 0 (A) is confirm (Enter)
- button 1 (B) is cancel (Esc)
- button 2 (X) is switch (Space)
- button 3 (Y) is delete (Delete)
- axes 0 and 1 (main analog pad) maps to cursor keys
- all hats (D-pads) map to cursor keys
Title screens and credits can be confirmed
with any joystick button or axis motion too.
Cross-play between development builds from different commits is never
guaranteed. Increase the protocol version number to force everyone to
sync up. Github user D2Lovin reported that mixing users from two
snapshot builds behaved poorly, but went silent when prompted for more
information. This bump will force users to synchronize, which is a good
idea on principle.
Related: https://github.com/dxx-rebirth/dxx-rebirth/issues/509
This was once a compatibility shim, but compiler support for std::begin
has been required since 5e434cbe95 and no
issues have been reported. Flatten the include tree by removing this
header and using the STL names directly.
A declaration is useful if it declares an external function. A static
inline declaration, if not followed by the definition later in the same
translation unit, will not be useful. Remove such declarations, and
rely on using the definition as a declaration for those files that
actually call partial_range() or similar functions.
The automap code keeps a mostly-private secondary copy of control_info.
The change to reset control_info before the event loop reset the main
copy of control_info for the automap, not the copy that the automap
actually used. Fix this by passing the desired control_info to relevant
functions instead of always using the global variable Controls.
Fixes: c621a970c6 ("Reset kconfig counters once, before the event loop")
This field is used in the SDL build for rendering. In the GL build, its
only purpose is for the editor to write it to a PIG file. Change that
one use to compute the value as needed. Move all other references
behind a preprocessor test for !DXX_USE_OGL. This shrinks the size of
grs_bitmap by 1 pointer, since the compiler added padding after
avg_color up to the size of the next aligned pointer.
gcc has a special case to devolve to memset if both the pointed-at data
and the value to fill are considered a byte. All uses of
DXX_POISON_MEMORY pass a value that fits in a byte, so change the
signature to be a byte, to encourage gcc to activate the special case.
This adds a new dependency, but most systems likely already have
SDL_image installed. Use of SDL_image can be disabled, but this is
discouraged, because various in-game interfaces assume the use of the
original background.
The old implementation automatically corrected for filename case. The
new implementation expects that the supplied filename can be passed to
PYHSFS_openRead as-is. All known uses in-game have been corrected to
satisfy this requirement. If the new stricter match requirement becomes
a problem, a variant of PHYSFSRWOPS_openRead that adjusts filename case
could be created for use here.
- Update install instructions
- Update ebuild
- Update Arch PKGBUILD
gcc-10 warns that the game information text may be truncated, because it
overestimates the maximum possible length of some strings. Handle the
warning by changing the format string to explicitly truncate these
strings at their maximum legal lengths.
mmontag reports that tool_bundle.py cannot be parsed under Python 3.
Fortunately, the errors are all straightforward, so non-OS X systems can
see the errors when the file is imported. Normally, the file is only
imported when building for darwin, so non-OS X systems do not see the
problem.
- Add parentheses to print() calls. This is not consistent with the
rest of the Rebirth output scheme, but is simple to do.
- Adjust the syntax for raising exceptions.
Reported-by: mmontag <https://github.com/dxx-rebirth/dxx-rebirth/issues/503#issuecomment-619463994>
Switch valptridx error style dispatching from using macro pasting to
using C++11 user-defined literals. This makes the code a bit easier to
read, and removes the need for a C99-conforming preprocessor here, which
should help anyone trying to port to Microsoft Visual Studio.
The new implementation also fixes a limitation of the previous
implementation. Before, an override that referenced an invalid name
could be silently ignored. Now, incorrect overrides cause an attempt to
use an undefined instantiation, which fails with a compilation error.
The minimum supported compiler versions now provide a depth-efficient
implementation of std::make_index_sequence, which removes the last
reason to carry a private implementation. In the case of clang, it
appears to have a special compiler intrinsic used to implement its
std::make_index_sequence.
Switch to the compiler-provided version for both gcc and clang.
Commit d355ef4030 removed a seemingly unnecessary modification of the
global variable grd_curcanv->cv_font, after eliminating all local reads
of it. However, a non-local read, buried in listbox_mouse, depended on
grd_curcanv->cv_font being set to a MEDIUM font. After that commit,
grd_curcanv->cv_font retained its prior value, which is not a MEDIUM
font. This caused listbox_mouse to compute an incorrect height of the
lines in the listbox, which manifested as the game choosing the wrong
line when the mouse is clicked in the listbox.
Fix the problem by explicitly using MEDIUM3_FONT, since that was
usually the value left in grd_curcanv->cv_font prior to that commit. In
some cases, a different MEDIUM font would be left there, but all the
MEDIUM fonts have the same height, so they are interchangeable for this
purpose.
Reported-by: Q3BFG10K <https://github.com/dxx-rebirth/dxx-rebirth/issues/498>
Fixes: d355ef4030 ("Pass font to various drawing functions")
gcc before gcc-7 failed to build valptridx:
```
common/include/valptridx.h: In instantiation of 'valptridx<managed_type>::ptridx<policy>::ptridx(const valptridx<managed_type>::ptridx<rpolicy>&) [with rpolicy =
valptridx<dcx::segment>::vm; typename std::enable_if<(policy:: allow_nullptr || (! rpolicy:: allow_nullptr)), int>::type <anonymous> = 0; policy = valptridx<dcx::segment>::vc; managed_type = dcx::segment]':
similar/main/endlevel.cpp:586:105: required from here
common/include/valptridx.h:686:14: error: 'using vptr_type = class valptridx<dcx::segment>::ptr<valptridx<dcx::segment>::vm>' is protected within this context
vptr_type(static_cast<const typename ptridx<rpolicy>::vptr_type &>(rhs)),
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
common/include/valptridx.h:666:31: note: declared protected here
using vptr_type = ptr<policy>;
```
This cannot be fixed in the obvious way because the error message is
wrong:
```
664 using containing_type = valptridx<managed_type>;
665 public:
666 using vptr_type = ptr<policy>;
667 using vidx_type = idx<policy>;
668 using typename vidx_type::array_managed_type;
```
The type declarations _already are_ *public*, not *protected* as the
message states. Relaxing the protection on the containing class
resolves the error. This looks bad from an encapsulation perspective,
but does not make the code incorrect.
The historical savegame format cannot support finding a mission in a
subdirectory. Add a backwards-incompatible modification to store the
full path in the savegame, and store it in a way that old versions will
fail gracefully.[1] When loading demos, or legacy savegames, search for
the mission in all available directories. Demos are still written with
an unqualified path because the demo loading code would crash if given
an oversized path. Mission names sent over the network as part of
multiplayer use the guess logic now, so that guests do not need to have
the mission in the same path as the host.
[1] Versions affected by issue #486 may fail ungracefully.
Reported-by: AlumiuN <https://github.com/dxx-rebirth/dxx-rebirth/issues/491>
- In D2X, do not accept Descent2-specific directives from Descent 1
`.msn` files.
- Set the descent_version field correctly in the `mle`. Previously,
`.msn` was set to descent1 and all `.mn2` were set to descent2,
regardless of whether the `.mn2` used `name`, `xname`, `zname`, or
`!name`.
- Avoid rewinding the file and rereading the same line while checking
the possible name types.
- Avoid recomputing end-of-string when it is already known.
- Avoid re-reading the mission file's version when the mission is
chosen. Instead, use the version that was recorded when the mission
was loaded into the mission list. This also fixes a bug where Descent
1 `.msn` files would be classified as descent_version_type::descent2
since both use `name =`, but that string has a different meaning
depending on whether the file is `.msn` or `.mn2`.
arch_close calls various library shutdown routines, some of which may
not be in good order after atexit hooks begin executing. Call it before
returning from main, so that the libraries are still fully initialized.
endlevel wants to freeze the console player's last in-mine position.
Instead of copying the position out and back, refactor the flow to let
endlevel skip the update of the position.
Only the console player's last position needs to be remembered across
frames. Copy the console player's position out before processsing
object movement. For all other objects, retain a temporary for use by
the position recovery code.
Various functions need to access both `shared_segment` and
`unique_segment` data. Using `segment &` for this blocks eliminating
the `segment` type. Add `susegment` and type aliases to it.
`susegment` records a reference to a `shared_segment` and a
`unique_segment` together, so that users cannot accidentally mismatch
`shared_segment` #1 with `unique_segment` #2 when passing references
down to a function which needs both `shared_segment` and
`unique_segment`.
gcc considers strong_typedef to be POD both with and without the
explicit default. clang considers it to be POD only if the constructor
is explicitly defaulted.
For correctness, valptridx::ptridx instances must not be sliced down to
their component ::ptr or ::idx base classes. Previously, this was done
with a dummy template parameter to ensure that a bare ::idx had a
different type than the idx base of a ::ptridx. This extra distinction
complicates analysis of the code, and is not needed when the code is
already correct. Add the ability to build without slice checking.
Fix a bug where the ptridx converting move constructor delegated to the
ptr converting copy constructor, since the ptr copy constructor had
filename/line arguments, the ptr move constructor did not, and the
ptridx move constructor always passed filename/line.
Difficulty_level_type is used in arithmetic expressions. If
Difficulty_level_type is unsigned, then those expressions use unsigned
terms, but some of the expressions were designed to use signed terms and
produce incorrect results when used with unsigned terms. There is no
strong reason to make Difficulty_level_type unsigned, so switch it to
signed instead of trying to fix every site that uses it.
Reported-by: AlumiuN <https://github.com/dxx-rebirth/dxx-rebirth/issues/471>
Fixes: 1eaaff3016 ("Move Difficulty_level to GameUniqueState")
Descent 2 has a hack, present as far back as I can trace, that
suppresses starting sounds during level load. The original reason was
not recorded, but this hack has the useful side effect that it avoids
using uninitialized data when set_sound_sources tries to use a Viewer
that has not been reset for the objects of the new level.
Descent 1 lacks this hack, so an invalid Viewer is used, which may
trigger a valptridx trap if the undefined data has an invalid segment
number, and could cause memory corruption in builds which do not
validate the segment index. The valptridx trap:
```
terminate called after throwing an instance of 'valptridx<dcx::segment>::index_range_exception'
what(): similar/main/digiobj.cpp:389: invalid index used in array subscript: base=(nil) size=9000 index=65021
```
The backtrace leading to the trap:
```
d1x::digi_link_sound_common (viewer=..., so=..., pos=..., forever=<optimized out>, max_volume=<optimized out>, max_distance=..., soundnum=42, segnum=...) at similar/main/digiobj.cpp:389
0x00005555555a4e2d in d1x::digi_link_sound_to_pos2 (vcobjptr=..., max_distance=..., max_volume=32768, forever=1, pos=..., sidenum=4, segnum=..., org_soundnum=121) at similar/main/digiobj.cpp:483
d1x::digi_link_sound_to_pos (soundnum=soundnum@entry=121, segnum=..., sidenum=sidenum@entry=4, pos=..., forever=forever@entry=1, max_volume=32768) at similar/main/digiobj.cpp:490
0x00005555555c140d in d1x::set_sound_sources (vcsegptridx=..., vcvertptr=...) at similar/main/gameseq.cpp:817
d1x::LoadLevel (level_num=<optimized out>, page_in_textures=1) at similar/main/gameseq.cpp:1022
0x00005555555c2654 in d1x::StartNewLevelSub (level_num=-1, page_in_textures=<optimized out>) at similar/main/gameseq.cpp:1865
```
Backport this hack into Descent 1. Ultimately, the hack should go away
and data should be loaded in an order that does not access undefined
memory.
Reported-by: Spacecpp <https://github.com/dxx-rebirth/dxx-rebirth/issues/463>
clang-9 reports:
```
similar/main/mglobal.cpp:210:44: error: 'report_error_uses_exception' is a protected member of 'valptridx_specialized_type_parameters<unsigned char, 90, valptridx_untyped_utilities::report_error_style::exception, valptridx_untyped_utilities::report_error_style::exception>'
template <typename T, bool = valptridx<T>::report_error_uses_exception::value>
^
similar/main/mglobal.cpp:229:16: note: in instantiation of default argument for 'instantiation_guard<dcx::active_door>' required here
template class instantiation_guard<dcx::active_door>::type::index_range_exception;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
common/include/fwd-valptridx.h:42:2: note: constrained by protected inheritance here
protected valptridx_specialized_types<managed_type>::type
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
common/include/cpp-valptridx.h:175:8: note: member is declared here
using report_error_uses_exception = std::integral_constant<bool,
```
Add a `using` statement to switch `report_error_uses_exception` to
`public` access. Nothing else uses it, and there is no design purpose
served by keeping it `protected`.
Each axis can act as two buttons in both ways.
For example, a player might map slide left and slide right to J1 -A1 and J1 +A1 as button presses instead of the slide L/R axis.
This is mostly to fix XBox 360 Controller Left and Right triggers. But it can work on every axis if the player wishes to bind them.
If the level was not the most recently played, a save is forced so that
it can be marked as most recently played. However, the logic to force
the save also forced an update of the highest-level field, even if that
reduced it.
- Rename the parameter to clarify its meaning.
- Add comments explaining the logic to force the save.
- Only update the highest-level field when the update would increase the saved value
The subcanvas is positioned based on the dimensions of the containing
window, so it must be repositioned if the outer window is resized.
Reported-by: vLKp <https://github.com/dxx-rebirth/dxx-rebirth/issues/394>
Fixes: f491059ed7 ("Enable building with SDL2")
exit_segnum is set during load_endlevel_data, which currently runs too
early for this to depend on the exit used, and thus to be player-unique.
That data should be loaded at need, when the level ends, rather than
during level setup. This can be addressed later, when support for
multiple exits is improved.
transition_segnum is a function of how the player exited the mine, since
there could be multiple exit tunnels, although current code appears not
to handle that well in other places. Therefore, it needs to be
per-player data, not part of the level data, where it would not depend
on the player exiting.
This could be a shared variable instead, since it cannot be directly
influenced by gameplay. However, it is influenced by the game mode, and
keeping shared variables that are mode-specific would be more complexity
for very little savings.
As documented in zico's commit 38fabd7c49, robot smart mines have a
different ID number than player smart mines. Rename the test functions
to clarify that they only recognize player smart mines, but not robot
smart mines.
git grep -l is_proximity_bomb_or_smart_mine | xargs sed -i -e 's/is_proximity_bomb_or_smart_mine/is_proximity_bomb_or_player_smart_mine/g'