Use enum for segnum_t
Add checked conversions for sites which load from external integers.
This commit is contained in:
parent
fca59adb53
commit
e25b476de7
|
@ -457,7 +457,6 @@ void editor_status( const char *text);
|
|||
extern int MacroNumEvents;
|
||||
extern int MacroStatus;
|
||||
|
||||
//extern int Highest_segment_index; // Highest index in Segments, an efficiency hack
|
||||
extern int Lock_view_to_cursegp; // !0 means whenever cursegp changes, view it
|
||||
|
||||
// eglobal.c
|
||||
|
|
|
@ -115,8 +115,21 @@ protected:
|
|||
static inline index_type check_index_range_size(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS std::size_t, const array_managed_type *);
|
||||
template <typename handle_index_mismatch, typename handle_index_range_error>
|
||||
static inline void check_explicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, std::size_t, const array_managed_type &);
|
||||
/* Given a reference `r` to an element that should be in the array `a`,
|
||||
* compute the array index `i` that should refer to `r`. Check that `i` is
|
||||
* within the bounds of the array, and that computing `&a[i]` yields `&r`.
|
||||
* The second test catches an error of the form:
|
||||
*
|
||||
* T a[3];
|
||||
* T *b = reinterpret_cast<char *>(&a[1]) + 1;
|
||||
* check_implicit_index_range_ref(*b, a);
|
||||
*
|
||||
* Use of the cast would allow the pointer to become misaligned and point
|
||||
* into the middle of an instance. Such a pointer would never be correct,
|
||||
* so detect and trap it here.
|
||||
*/
|
||||
template <typename handle_index_mismatch, typename handle_index_range_error>
|
||||
static inline void check_implicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type, const array_managed_type &);
|
||||
static inline void check_implicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type r, const array_managed_type &a);
|
||||
template <typename handle_null_pointer>
|
||||
static inline void check_null_pointer_conversion(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_pointer_type);
|
||||
template <typename handle_null_pointer>
|
||||
|
|
|
@ -293,6 +293,44 @@ template <typename range_exception, std::size_t required_buffer_size, typename P
|
|||
void check_range_object_size(const char *, unsigned, const char *, const P &&, std::size_t, std::size_t) {}
|
||||
#endif
|
||||
|
||||
template <typename range_type, typename index_type>
|
||||
std::true_type check_range_index_type_vs_provided_index_type(...);
|
||||
|
||||
template <
|
||||
typename range_type,
|
||||
typename provided_index_type,
|
||||
/* If `range_type::index_type` is not defined, fail.
|
||||
* If `range_type::index_type` is void, fail.
|
||||
*/
|
||||
typename range_index_type = typename std::remove_reference<typename std::remove_reference<range_type>::type::index_type &>::type
|
||||
>
|
||||
std::is_same<provided_index_type, range_index_type> check_range_index_type_vs_provided_index_type(std::nullptr_t);
|
||||
|
||||
template <typename range_type, typename index_type>
|
||||
typename std::enable_if<std::is_enum<index_type>::value, std::size_t>::type cast_index_to_size(const index_type i)
|
||||
{
|
||||
static_assert(std::is_unsigned<typename std::underlying_type<index_type>::type>::value, "underlying_type of index_type must be unsigned");
|
||||
/* If an enumerated index type is used, require that it be the type that
|
||||
* the underlying range uses.
|
||||
*/
|
||||
static_assert(decltype(check_range_index_type_vs_provided_index_type<range_type, index_type>(nullptr))::value);
|
||||
return static_cast<std::size_t>(i);
|
||||
}
|
||||
|
||||
template <typename range_type, typename index_type>
|
||||
typename std::enable_if<std::is_integral<index_type>::value, std::size_t>::type cast_index_to_size(const index_type i)
|
||||
{
|
||||
static_assert(std::is_unsigned<index_type>::value, "integral index_type must be unsigned");
|
||||
/* Omit enforcement of range_type::index_type vs index_type, since many
|
||||
* call sites provide numeric length limits.
|
||||
static_assert(decltype(check_range_index_type_vs_provided_index_type<range_type, index_type>(nullptr))::value);
|
||||
*/
|
||||
/* Use an implicit conversion, so that an index_type of std::size_t does
|
||||
* not cause a useless cast.
|
||||
*/
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <
|
||||
|
@ -360,9 +398,6 @@ inline auto (unchecked_partial_range)(
|
|||
#endif
|
||||
range_type &range, const index_begin_type &index_begin, const index_end_type &index_end)
|
||||
{
|
||||
/* Require unsigned length */
|
||||
static_assert(std::is_unsigned<index_begin_type>::value, "offset to partial_range must be unsigned");
|
||||
static_assert(std::is_unsigned<index_end_type>::value, "length to partial_range must be unsigned");
|
||||
static_assert(!std::is_void<reference>::value, "dereference of iterator must not be void");
|
||||
return unchecked_partial_range_advance<
|
||||
#ifdef DXX_HAVE_BUILTIN_OBJECT_SIZE
|
||||
|
@ -372,7 +407,9 @@ inline auto (unchecked_partial_range)(
|
|||
#ifdef DXX_HAVE_BUILTIN_OBJECT_SIZE
|
||||
file, line, estr,
|
||||
#endif
|
||||
std::begin(range), index_begin, index_end
|
||||
std::begin(range),
|
||||
partial_range_detail::cast_index_to_size<range_type, index_begin_type>(index_begin),
|
||||
partial_range_detail::cast_index_to_size<range_type, index_end_type>(index_end)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -462,19 +499,21 @@ template <
|
|||
[[nodiscard]]
|
||||
inline auto (partial_range)(const char *const file, const unsigned line, const char *const estr, range_type &range, const index_begin_type &index_begin, const index_end_type &index_end)
|
||||
{
|
||||
const auto sz_begin = partial_range_detail::cast_index_to_size<range_type, index_begin_type>(index_begin);
|
||||
const auto sz_end = partial_range_detail::cast_index_to_size<range_type, index_end_type>(index_end);
|
||||
partial_range_detail::check_range_bounds<
|
||||
typename partial_range_t<iterator_type, decltype(partial_range_detail::range_index_type<range_type>(nullptr))>::partial_range_error,
|
||||
required_buffer_size
|
||||
>(file, line, estr, reinterpret_cast<uintptr_t>(std::addressof(range)), index_begin, index_end, std::size(range));
|
||||
>(file, line, estr, reinterpret_cast<uintptr_t>(std::addressof(range)), sz_begin, sz_end, std::size(range));
|
||||
return unchecked_partial_range<
|
||||
#ifdef DXX_HAVE_BUILTIN_OBJECT_SIZE
|
||||
required_buffer_size,
|
||||
#endif
|
||||
range_type, index_begin_type, index_end_type>(
|
||||
range_type>(
|
||||
#ifdef DXX_HAVE_BUILTIN_OBJECT_SIZE
|
||||
file, line, estr,
|
||||
#endif
|
||||
range, index_begin, index_end
|
||||
range, sz_begin, sz_end
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,9 @@ public:
|
|||
class valptridx_detail::untyped_utilities::report_error_trap_terse
|
||||
{
|
||||
public:
|
||||
/* Accept and discard any arguments, to encourage the compiler to discard
|
||||
* as dead any values that exist only as arguments to `report()`.
|
||||
*/
|
||||
[[noreturn]]
|
||||
__attribute_cold
|
||||
DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT
|
||||
|
@ -114,6 +117,11 @@ public:
|
|||
DXX_VALPTRIDX_WARN_CALL_NOT_OPTIMIZED_OUT
|
||||
static void report(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const void *const array, const unsigned long supplied_index, const void *const expected_pointer, const void *const actual_pointer)
|
||||
{
|
||||
/* Load each of the arguments into storage before executing the trap,
|
||||
* so that inspection of those locations in the core dump can readily
|
||||
* retrieve these values, even if the values would otherwise be unused
|
||||
* and optimized out.
|
||||
*/
|
||||
__asm__ __volatile__("" :: DXX_VALPTRIDX_REPORT_STANDARD_ASM_LOAD_COMMA_R_VARS "rm" (array), "rm" (supplied_index), "rm" (expected_pointer), "rm" (actual_pointer));
|
||||
__builtin_trap();
|
||||
}
|
||||
|
@ -259,8 +267,8 @@ template <typename managed_type>
|
|||
template <typename handle_index_mismatch, typename handle_index_range_error>
|
||||
void valptridx<managed_type>::check_explicit_index_range_ref(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_DEFN_VARS const_reference_type &r, std::size_t i, const array_managed_type &a)
|
||||
{
|
||||
check_index_match<handle_index_mismatch>(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS r, i, a);
|
||||
check_index_range_size<handle_index_range_error>(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS i, &a);
|
||||
const auto ii = check_index_range_size<handle_index_range_error>(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS i, &a);
|
||||
check_index_match<handle_index_mismatch>(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS r, ii, a);
|
||||
}
|
||||
|
||||
template <typename managed_type>
|
||||
|
@ -268,7 +276,9 @@ class valptridx<managed_type>::partial_policy::require_valid
|
|||
{
|
||||
public:
|
||||
static constexpr std::false_type allow_nullptr{};
|
||||
[[nodiscard]]
|
||||
static constexpr std::false_type check_allowed_invalid_index(index_type) { return {}; }
|
||||
[[nodiscard]]
|
||||
static constexpr bool check_nothrow_index(index_type i)
|
||||
{
|
||||
return std::less<std::size_t>()(static_cast<std::size_t>(i), array_size);
|
||||
|
@ -280,10 +290,12 @@ class valptridx<managed_type>::partial_policy::allow_invalid
|
|||
{
|
||||
public:
|
||||
static constexpr std::true_type allow_nullptr{};
|
||||
[[nodiscard]]
|
||||
static constexpr bool check_allowed_invalid_index(index_type i)
|
||||
{
|
||||
return i == static_cast<index_type>(~0);
|
||||
}
|
||||
[[nodiscard]]
|
||||
static constexpr bool check_nothrow_index(index_type i)
|
||||
{
|
||||
return check_allowed_invalid_index(i) || require_valid::check_nothrow_index(i);
|
||||
|
@ -369,11 +381,10 @@ public:
|
|||
}
|
||||
template <typename rpolicy, typename std::enable_if<!(policy::allow_nullptr || !rpolicy::allow_nullptr), int>::type = 0>
|
||||
idx(const idx<rpolicy> &rhs DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_L_DECL_VARS) :
|
||||
m_idx(rhs.get_unchecked_index())
|
||||
{
|
||||
/* If moving from allow_invalid to require_valid, check range.
|
||||
*/
|
||||
check_index_range<index_range_error_type<array_managed_type>>(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS m_idx, nullptr);
|
||||
m_idx(check_index_range<index_range_error_type<array_managed_type>>(DXX_VALPTRIDX_REPORT_STANDARD_LEADER_COMMA_R_PASS_VARS rhs.get_unchecked_index(), nullptr))
|
||||
{
|
||||
}
|
||||
template <typename rpolicy>
|
||||
idx(idx<rpolicy> &&rhs) :
|
||||
|
|
|
@ -247,7 +247,7 @@ struct ai_static_rw
|
|||
{
|
||||
ubyte behavior; //
|
||||
int8_t flags[11]; // various flags, meaning defined by constants
|
||||
short hide_segment; // Segment to go to for hiding.
|
||||
uint16_t hide_segment; // Segment to go to for hiding.
|
||||
short hide_index; // Index in Path_seg_points
|
||||
short path_length; // Length of hide path.
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
namespace dcx {
|
||||
constexpr std::integral_constant<std::size_t, 9000> MAX_SEGMENTS{};
|
||||
using segnum_t = uint16_t;
|
||||
enum segnum_t : uint16_t;
|
||||
struct d_level_unique_automap_state;
|
||||
}
|
||||
#ifdef dsx
|
||||
|
@ -54,9 +54,9 @@ constexpr std::integral_constant<std::size_t, 4 * MAX_SEGMENTS> MAX_SEGMENT_VERT
|
|||
#ifdef dsx
|
||||
DXX_VALPTRIDX_DEFINE_SUBTYPE_TYPEDEFS(segment, seg);
|
||||
|
||||
static constexpr valptridx<segment>::magic_constant<0xfffe> segment_exit{};
|
||||
static constexpr valptridx<segment>::magic_constant<0xffff> segment_none{};
|
||||
static constexpr valptridx<segment>::magic_constant<0> segment_first{};
|
||||
static constexpr valptridx<segment>::magic_constant<segnum_t{0xfffe}> segment_exit{};
|
||||
static constexpr valptridx<segment>::magic_constant<segnum_t{0xffff}> segment_none{};
|
||||
static constexpr valptridx<segment>::magic_constant<segnum_t{0}> segment_first{};
|
||||
#endif
|
||||
}
|
||||
#ifdef dsx
|
||||
|
|
|
@ -927,3 +927,8 @@ static inline unsigned get_player_or_team_color(unsigned pnum)
|
|||
? get_team_color(get_team(pnum))
|
||||
: get_player_color(pnum);
|
||||
}
|
||||
|
||||
#define PUT_INTEL_SEGNUM(D,S) ( DXX_BEGIN_COMPOUND_STATEMENT { \
|
||||
const segnum_t PUT_INTEL_SEGNUM = S; \
|
||||
PUT_INTEL_SHORT(D, static_cast<uint16_t>(PUT_INTEL_SEGNUM)); \
|
||||
} DXX_END_COMPOUND_STATEMENT )
|
||||
|
|
|
@ -479,7 +479,7 @@ struct object_rw
|
|||
ubyte movement_source; // how this object moves
|
||||
ubyte render_type; // how this object renders
|
||||
ubyte flags; // misc flags
|
||||
short segnum; // segment number containing object
|
||||
uint16_t segnum; // segment number containing object
|
||||
short attached_obj; // number of attached fireball object
|
||||
vms_vector pos; // absolute x,y,z coordinate of center of object
|
||||
vms_matrix orient; // orientation of object in world
|
||||
|
|
|
@ -33,7 +33,6 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#include "dxxsconf.h"
|
||||
#include "dsx-ns.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
@ -43,7 +42,6 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#include "objnum.h"
|
||||
#include "pack.h"
|
||||
|
||||
|
||||
#ifdef dsx
|
||||
namespace dsx {
|
||||
// Returns true if segnum references a child, else returns false.
|
||||
|
@ -122,6 +120,10 @@ enum class station_number : uint8_t
|
|||
None = 0xff,
|
||||
};
|
||||
|
||||
enum segnum_t : uint16_t
|
||||
{
|
||||
};
|
||||
|
||||
struct shared_side
|
||||
{
|
||||
struct illegal_type;
|
||||
|
@ -338,7 +340,7 @@ struct group
|
|||
};
|
||||
|
||||
#ifdef dsx
|
||||
#define Highest_segment_index (Segments.get_count() - 1)
|
||||
#define Highest_segment_index static_cast<segnum_t>(Segments.get_count() - 1)
|
||||
DXX_VALPTRIDX_DEFINE_GLOBAL_FACTORIES(segment, seg, Segments);
|
||||
#endif
|
||||
|
||||
|
@ -642,4 +644,3 @@ extern d_level_shared_segment_state LevelSharedSegmentState;
|
|||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -915,7 +915,6 @@ int rotate_segment_new(const vms_angvec &pbh)
|
|||
{
|
||||
vms_matrix tm1;
|
||||
group::segment_array_type_t selected_segs_save;
|
||||
int child_save;
|
||||
int current_group_save;
|
||||
|
||||
if (!IS_CHILD(Cursegp->children[Side_opposite[Curside]]))
|
||||
|
@ -936,7 +935,7 @@ int rotate_segment_new(const vms_angvec &pbh)
|
|||
|
||||
// Create list of segments to rotate.
|
||||
// Sever connection between first seg to rotate and its connection on Side_opposite[Curside].
|
||||
child_save = Cursegp->children[newseg_side]; // save connection we are about to sever
|
||||
const auto child_save = Cursegp->children[newseg_side]; // save connection we are about to sever
|
||||
Cursegp->children[newseg_side] = segment_none; // sever connection
|
||||
create_group_list(Cursegp, GroupList[ROT_GROUP].segments, NULL); // create list of segments in group
|
||||
Cursegp->children[newseg_side] = child_save; // restore severed connection
|
||||
|
|
|
@ -135,7 +135,7 @@ int SaveGameData()
|
|||
if (Perm_player_segnum!=segment_none) {
|
||||
|
||||
if (save_segnum > Highest_segment_index)
|
||||
save_segnum = 0;
|
||||
save_segnum = {};
|
||||
|
||||
ConsoleObject->pos = save_pos;
|
||||
const auto &&save_segp = vmsegptridx(save_segnum);
|
||||
|
|
|
@ -231,9 +231,7 @@ int wall_add_external_wall()
|
|||
editor_status( "Cannot add external wall here - seg has children" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
Cursegp->children[Curside] = -2;
|
||||
|
||||
Cursegp->children[Curside] = segment_exit;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -593,9 +593,9 @@ int save_mine_data_compiled(PHYSFS_File *SaveFile)
|
|||
PHYSFSX_writeVector(SaveFile, i);
|
||||
|
||||
const auto Num_segments = LevelSharedSegmentState.Num_segments;
|
||||
for (segnum_t segnum = 0; segnum < Num_segments; segnum++)
|
||||
auto &&segment_range = partial_const_range(Segments, Num_segments);
|
||||
for (const cscusegment seg : segment_range)
|
||||
{
|
||||
const cscusegment &&seg = vcsegptr(segnum);
|
||||
{
|
||||
sidemask_t bit_mask{};
|
||||
for (const auto &&[sidenum, child] : enumerate(seg.s.children))
|
||||
|
@ -689,8 +689,8 @@ int save_mine_data_compiled(PHYSFS_File *SaveFile)
|
|||
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
if (Gamesave_current_version > 5)
|
||||
for (segnum_t i = 0; i < Num_segments; i++)
|
||||
segment2_write(vcsegptr(i), SaveFile);
|
||||
for (auto &s : segment_range)
|
||||
segment2_write(s, SaveFile);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -172,8 +172,9 @@ namespace dsx {
|
|||
// Scans the Segments array.
|
||||
segnum_t get_free_segment_number(segment_array &Segments)
|
||||
{
|
||||
for (segnum_t segnum=0; segnum<MAX_SEGMENTS; segnum++)
|
||||
if (Segments[segnum].segnum == segment_none) {
|
||||
for (const auto &&[segnum, seg] : enumerate(Segments))
|
||||
if (seg.segnum == segment_none)
|
||||
{
|
||||
++ LevelSharedSegmentState.Num_segments;
|
||||
if (segnum > Highest_segment_index)
|
||||
Segments.set_count(segnum + 1);
|
||||
|
@ -181,8 +182,7 @@ segnum_t get_free_segment_number(segment_array &Segments)
|
|||
}
|
||||
|
||||
Assert(0);
|
||||
|
||||
return 0;
|
||||
return segnum_t{};
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
|
@ -936,8 +936,9 @@ int med_delete_segment(const vmsegptridx_t sp)
|
|||
|
||||
// If we deleted something which was not connected to anything, must now select a new current segment.
|
||||
if (Cursegp == sp)
|
||||
for (segnum_t s=0; s<MAX_SEGMENTS; s++)
|
||||
if ((Segments[s].segnum != segment_none) && (s!=segnum) ) {
|
||||
for (auto &&[s, seg] : enumerate(Segments))
|
||||
if (seg.segnum != segment_none && s != segnum)
|
||||
{
|
||||
Cursegp = imsegptridx(s);
|
||||
med_create_new_segment_from_cursegp();
|
||||
break;
|
||||
|
@ -1283,7 +1284,7 @@ void med_create_segment(const vmsegptridx_t sp,fix cx, fix cy, fix cz, fix lengt
|
|||
auto &Vertices = LevelSharedVertexState.get_vertices();
|
||||
++ LevelSharedSegmentState.Num_segments;
|
||||
|
||||
sp->segnum = 1; // What to put here? I don't know.
|
||||
sp->segnum = segnum_t{1}; // What to put here? I don't know.
|
||||
|
||||
// Form connections to children, of which it has none.
|
||||
for (auto &&[child, side] : zip(sp->children, sp->shared_segment::sides))
|
||||
|
@ -1349,7 +1350,7 @@ void med_create_new_segment(const vms_vector &scale)
|
|||
width = scale.x;
|
||||
height = scale.y;
|
||||
|
||||
sp->segnum = 1; // What to put here? I don't know.
|
||||
sp->segnum = segnum_t{1}; // What to put here? I don't know.
|
||||
|
||||
// Create relative-to-center vertices, which are the points on the box defined by length, width, height
|
||||
auto &verts = sp->verts;
|
||||
|
|
|
@ -4626,7 +4626,7 @@ static void state_ai_local_to_ai_local_rw(const ai_local *ail, ai_local_rw *ail_
|
|||
ail_rw->mode = static_cast<uint8_t>(ail->mode);
|
||||
ail_rw->previous_visibility = static_cast<int8_t>(ail->previous_visibility);
|
||||
ail_rw->rapidfire_count = ail->rapidfire_count;
|
||||
ail_rw->goal_segment = ail->goal_segment;
|
||||
ail_rw->goal_segment = underlying_value(ail->goal_segment);
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
ail_rw->last_see_time = 0;
|
||||
ail_rw->last_attack_time = 0;
|
||||
|
@ -4832,7 +4832,10 @@ static void ai_local_read_swap(ai_local *ail, int swap, PHYSFS_File *fp)
|
|||
ail->mode = static_cast<ai_mode>(PHYSFSX_readByte(fp));
|
||||
ail->previous_visibility = static_cast<player_visibility_state>(PHYSFSX_readByte(fp));
|
||||
ail->rapidfire_count = PHYSFSX_readByte(fp);
|
||||
ail->goal_segment = PHYSFSX_readSXE16(fp, swap);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readSXE16(fp, swap))};
|
||||
ail->goal_segment = imsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
PHYSFSX_readSXE32(fp, swap);
|
||||
PHYSFSX_readSXE32(fp, swap);
|
||||
ail->next_action_time = PHYSFSX_readSXE32(fp, swap);
|
||||
|
@ -4844,7 +4847,10 @@ static void ai_local_read_swap(ai_local *ail, int swap, PHYSFS_File *fp)
|
|||
ail->mode = static_cast<ai_mode>(PHYSFSX_readSXE32(fp, swap));
|
||||
ail->previous_visibility = static_cast<player_visibility_state>(PHYSFSX_readSXE32(fp, swap));
|
||||
ail->rapidfire_count = PHYSFSX_readSXE32(fp, swap);
|
||||
ail->goal_segment = PHYSFSX_readSXE32(fp, swap);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readSXE32(fp, swap))};
|
||||
ail->goal_segment = imsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
ail->next_action_time = PHYSFSX_readSXE32(fp, swap);
|
||||
ail->next_fire = PHYSFSX_readSXE32(fp, swap);
|
||||
ail->next_fire2 = PHYSFSX_readSXE32(fp, swap);
|
||||
|
@ -4897,7 +4903,10 @@ static void ai_cloak_info_read_n_swap(ai_cloak_info *ci, int n, int swap, PHYSFS
|
|||
tmptime32 = PHYSFSX_readSXE32(fp, swap);
|
||||
ci->last_time = static_cast<fix64>(tmptime32);
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
ci->last_segment = PHYSFSX_readSXE32(fp, swap);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readSXE32(fp, swap))};
|
||||
ci->last_segment = imsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
#endif
|
||||
PHYSFSX_readVectorX(fp, ci->last_position, swap);
|
||||
}
|
||||
|
@ -5022,16 +5031,24 @@ int ai_restore_state(PHYSFS_File *fp, int version, int swap)
|
|||
ai_reset_all_paths();
|
||||
|
||||
if (version >= 21) {
|
||||
unsigned Num_boss_teleport_segs = PHYSFSX_readSXE32(fp, swap);
|
||||
unsigned Num_boss_gate_segs = PHYSFSX_readSXE32(fp, swap);
|
||||
const xrange Num_boss_teleport_segs = static_cast<unsigned>(PHYSFSX_readSXE32(fp, swap));
|
||||
const xrange Num_boss_gate_segs = static_cast<unsigned>(PHYSFSX_readSXE32(fp, swap));
|
||||
|
||||
Boss_gate_segs.clear();
|
||||
for (unsigned i = 0; i < Num_boss_gate_segs; i++)
|
||||
Boss_gate_segs.emplace_back(PHYSFSX_readSXE16(fp, swap));
|
||||
for (const auto i : Num_boss_gate_segs)
|
||||
{
|
||||
(void)i;
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readSXE16(fp, swap))};
|
||||
Boss_gate_segs.emplace_back(s);
|
||||
}
|
||||
|
||||
Boss_teleport_segs.clear();
|
||||
for (unsigned i = 0; i < Num_boss_teleport_segs; i++)
|
||||
Boss_teleport_segs.emplace_back(PHYSFSX_readSXE16(fp, swap));
|
||||
for (const auto i : Num_boss_teleport_segs)
|
||||
{
|
||||
(void)i;
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readSXE16(fp, swap))};
|
||||
Boss_teleport_segs.emplace_back(s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1546,7 +1546,7 @@ static void test_create_all_paths(fvmobjptridx &vmobjptridx, fvcsegptridx &vcseg
|
|||
const shared_segment &sseg0 = segp0;
|
||||
if (sseg0.segnum != segment_none)
|
||||
{
|
||||
range_for (const auto &&segp1, partial_range(vcsegptridx, static_cast<segnum_t>(segp0), vcsegptridx.count()))
|
||||
for (const auto &&segp1 : partial_range(vcsegptridx, segp0.get_unchecked_index(), vcsegptridx.count()))
|
||||
{
|
||||
const shared_segment &sseg1 = segp1;
|
||||
if (sseg1.segnum != segment_none)
|
||||
|
|
|
@ -820,8 +820,8 @@ static vmsegptridx_t choose_drop_segment(fvmsegptridx &vmsegptridx, fvcvertptr &
|
|||
* Give up and pick a completely random segment. This is compatible
|
||||
* with retail.
|
||||
*/
|
||||
std::uniform_int_distribution uid(0u, Highest_segment_index);
|
||||
return vmsegptridx(vmsegidx_t(uid(mrd)));
|
||||
std::uniform_int_distribution<typename std::underlying_type<segnum_t>::type> uid(0u, Highest_segment_index);
|
||||
return vmsegptridx(vmsegidx_t(segnum_t{uid(mrd)}));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
|
@ -1692,7 +1692,10 @@ void expl_wall_read_n_swap(fvmwallptr &vmwallptr, PHYSFS_File *const fp, const i
|
|||
d.sidenum = SWAPINT(d.sidenum);
|
||||
d.time = SWAPINT(d.time);
|
||||
}
|
||||
const icsegidx_t dseg = d.segnum;
|
||||
const auto s = segnum_t{static_cast<uint16_t>(d.segnum)};
|
||||
if (!vmsegidx_t::check_nothrow_index(s))
|
||||
continue;
|
||||
const icsegidx_t dseg = s;
|
||||
if (dseg == segment_none)
|
||||
continue;
|
||||
range_for (auto &&wp, vmwallptr)
|
||||
|
@ -1756,8 +1759,9 @@ vmsegidx_t choose_thief_recreation_segment(fvcsegptr &vcsegptr, fvcwallptr &vcwa
|
|||
* Give up and pick a completely random segment. This is compatible
|
||||
* with retail Descent 2.
|
||||
*/
|
||||
std::uniform_int_distribution uid(0u, Highest_segment_index);
|
||||
return uid(mrd);
|
||||
using distribution_type = typename std::underlying_type<segnum_t>::type;
|
||||
std::uniform_int_distribution uid(distribution_type{0}, static_cast<distribution_type>(Highest_segment_index));
|
||||
return segnum_t{uid(mrd)};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -645,7 +645,8 @@ fvi_hit_type find_vector_intersection(const fvi_query &fq, fvi_info &hit_data)
|
|||
{
|
||||
Assert(fq.startseg <= Highest_segment_index);
|
||||
hit_data.hit_pnt = *fq.p0;
|
||||
hit_data.hit_seg = hit_data.hit_object = 0;
|
||||
hit_data.hit_seg = segnum_t{};
|
||||
hit_data.hit_object = 0;
|
||||
hit_data.hit_side = side_none;
|
||||
hit_data.hit_side_seg = segment_none;
|
||||
return fvi_hit_type::BadP0;
|
||||
|
|
|
@ -2457,7 +2457,10 @@ namespace dsx {
|
|||
*/
|
||||
void flickering_light_read(flickering_light &fl, PHYSFS_File *fp)
|
||||
{
|
||||
fl.segnum = PHYSFSX_readShort(fp);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(fp))};
|
||||
fl.segnum = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
const auto sidenum = build_sidenum_from_untrusted(PHYSFSX_readShort(fp));
|
||||
fl.mask = PHYSFSX_readInt(fp);
|
||||
fl.timer = PHYSFSX_readFix(fp);
|
||||
|
|
|
@ -408,7 +408,8 @@ static void read_children(shared_segment &segp, const sidemask_t bit_mask, PHYSF
|
|||
{
|
||||
if (bit_mask & build_sidemask(bit))
|
||||
{
|
||||
segp.children[bit] = PHYSFSX_readShort(LoadFile);
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(LoadFile))};
|
||||
segp.children[bit] = (imsegidx_t::check_nothrow_index(s) || s == segment_exit) ? s : segment_none;
|
||||
} else
|
||||
segp.children[bit] = segment_none;
|
||||
}
|
||||
|
@ -501,11 +502,21 @@ int load_mine_data_compiled(PHYSFS_File *LoadFile, const char *const Gamesave_cu
|
|||
PHYSFSX_readVector(LoadFile, i);
|
||||
|
||||
const auto Num_segments = LevelSharedSegmentState.Num_segments;
|
||||
for (segnum_t segnum=0; segnum < Num_segments; segnum++ ) {
|
||||
const msmusegment segp = vmsegptr(segnum);
|
||||
/* Editor builds need both the segment index and segment pointer.
|
||||
* Non-editor builds need only the segment pointer.
|
||||
*/
|
||||
#if DXX_USE_EDITOR
|
||||
#define dxx_segment_iteration_factory vmptridx
|
||||
#else
|
||||
#define dxx_segment_iteration_factory vmptr
|
||||
#endif
|
||||
for (auto &&segpi : partial_range(Segments.dxx_segment_iteration_factory, Num_segments))
|
||||
#undef dxx_segment_iteration_factory
|
||||
{
|
||||
const msmusegment segp = segpi;
|
||||
|
||||
#if DXX_USE_EDITOR
|
||||
segp.s.segnum = segnum;
|
||||
segp.s.segnum = segpi;
|
||||
segp.s.group = 0;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -426,7 +426,10 @@ static void read_object(const vmobjptr_t obj,PHYSFS_File *f,int version)
|
|||
}
|
||||
obj->flags = PHYSFSX_readByte(f);
|
||||
|
||||
obj->segnum = PHYSFSX_readShort(f);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(f))};
|
||||
obj->segnum = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
obj->attached_obj = object_none;
|
||||
|
||||
PHYSFSX_readVector(f, obj->pos);
|
||||
|
@ -496,7 +499,10 @@ static void read_object(const vmobjptr_t obj,PHYSFS_File *f,int version)
|
|||
obj->ctype.ai_info.SKIP_AI_COUNT = ai_info_flags[7];
|
||||
obj->ctype.ai_info.REMOTE_OWNER = ai_info_flags[8];
|
||||
obj->ctype.ai_info.REMOTE_SLOT_NUM = ai_info_flags[9];
|
||||
obj->ctype.ai_info.hide_segment = PHYSFSX_readShort(f);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(f))};
|
||||
obj->ctype.ai_info.hide_segment = imsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
obj->ctype.ai_info.hide_index = PHYSFSX_readShort(f);
|
||||
obj->ctype.ai_info.path_length = PHYSFSX_readShort(f);
|
||||
obj->ctype.ai_info.cur_path_index = PHYSFSX_readShort(f);
|
||||
|
@ -902,7 +908,7 @@ static void validate_segment_wall(const vcsegptridx_t seg, shared_side &side, co
|
|||
if (connected_seg == segment_none)
|
||||
{
|
||||
rwn0 = wall_none;
|
||||
LevelError("segment %u side %u wall %u has no child segment; removing orphan wall.", seg.get_unchecked_index(), underlying_value(sidenum), static_cast<unsigned>(wn0));
|
||||
LevelError("segment %hu side %u wall %hu has no child segment; removing orphan wall.", seg.get_unchecked_index(), underlying_value(sidenum), underlying_value(wn0));
|
||||
return;
|
||||
}
|
||||
const shared_segment &vcseg = *vcsegptr(connected_seg);
|
||||
|
@ -910,14 +916,14 @@ static void validate_segment_wall(const vcsegptridx_t seg, shared_side &side, co
|
|||
if (connected_side == side_none)
|
||||
{
|
||||
rwn0 = wall_none;
|
||||
LevelError("segment %u side %u wall %u has child segment %u side %u, but child segment does not link back; removing orphan wall.", seg.get_unchecked_index(), underlying_value(sidenum), underlying_value(wn0), connected_seg, underlying_value(connected_side));
|
||||
LevelError("segment %hu side %u wall %u has child segment %hu side %u, but child segment does not link back; removing orphan wall.", seg.get_unchecked_index(), underlying_value(sidenum), underlying_value(wn0), connected_seg, underlying_value(connected_side));
|
||||
return;
|
||||
}
|
||||
const auto wn1 = vcseg.sides[connected_side].wall_num;
|
||||
if (wn1 == wall_none)
|
||||
{
|
||||
rwn0 = wall_none;
|
||||
LevelError("segment %u side %u wall %u has child segment %u side %u, but no wall; removing orphan wall.", seg.get_unchecked_index(), underlying_value(sidenum), static_cast<unsigned>(wn0), connected_seg, underlying_value(connected_side));
|
||||
LevelError("segment %hu side %u wall %u has child segment %hu side %u, but no wall; removing orphan wall.", seg.get_unchecked_index(), underlying_value(sidenum), static_cast<unsigned>(wn0), connected_seg, underlying_value(connected_side));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1136,7 +1142,7 @@ static int load_game_data(
|
|||
matcen_info_read(LoadFile, r);
|
||||
#endif
|
||||
// Set links in RobotCenters to Station array
|
||||
range_for (const shared_segment &seg, partial_const_range(Segments, Highest_segment_index + 1))
|
||||
for (const shared_segment &seg : partial_const_range(Segments, Segments.get_count()))
|
||||
if (seg.special == segment_special::robotmaker)
|
||||
if (seg.matcen_num == i)
|
||||
r.fuelcen_num = seg.station_idx;
|
||||
|
@ -1187,7 +1193,7 @@ static int load_game_data(
|
|||
auto objsegnum = i.segnum;
|
||||
if (objsegnum > Highest_segment_index) //bogus object
|
||||
{
|
||||
Warning("Object %p is in non-existent segment %i, highest=%i", &i, objsegnum, Highest_segment_index);
|
||||
Warning("Object %p is in non-existent segment %hu, highest=%hu", &i, objsegnum, Highest_segment_index);
|
||||
i.type = OBJ_NONE;
|
||||
}
|
||||
else {
|
||||
|
@ -1437,7 +1443,10 @@ int load_level(
|
|||
Secret_return_orient.uvec.y = 0;
|
||||
Secret_return_orient.uvec.z = F1_0;
|
||||
} else {
|
||||
LevelSharedSegmentState.Secret_return_segment = PHYSFSX_readInt(LoadFile);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readInt(LoadFile))};
|
||||
LevelSharedSegmentState.Secret_return_segment = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
Secret_return_orient.rvec.x = PHYSFSX_readInt(LoadFile);
|
||||
Secret_return_orient.rvec.y = PHYSFSX_readInt(LoadFile);
|
||||
Secret_return_orient.rvec.z = PHYSFSX_readInt(LoadFile);
|
||||
|
@ -1470,7 +1479,7 @@ int load_level(
|
|||
*/
|
||||
if (Current_mission && !d_stricmp("Descent 2: Counterstrike!", Current_mission->mission_name) && !d_stricmp("d2levc-4.rl2", filename))
|
||||
{
|
||||
shared_segment &s104 = *vmsegptr(vmsegidx_t(104));
|
||||
shared_segment &s104 = *vmsegptr(segnum_t{104});
|
||||
auto &s104v0 = *vmvertptr(s104.verts[segment_relative_vertnum::_0]);
|
||||
auto &s104s1 = s104.sides[sidenum_t::WTOP];
|
||||
auto &s104s1n0 = s104s1.normals[0];
|
||||
|
|
|
@ -531,8 +531,9 @@ int check_segment_connections(void)
|
|||
{
|
||||
shared_segment &rseg = *seg;
|
||||
const shared_segment &rcseg = *cseg;
|
||||
const unsigned segi = seg.get_unchecked_index();
|
||||
LevelError("Segment #%u side %u has asymmetric link to segment %u. Coercing to segment_none; Segments[%u].children={%hu, %hu, %hu, %hu, %hu, %hu}, Segments[%u].children={%hu, %hu, %hu, %hu, %hu, %hu}.", segi, underlying_value(sidenum), csegnum, segi, rseg.children[sidenum_t::WLEFT], rseg.children[sidenum_t::WTOP], rseg.children[sidenum_t::WRIGHT], rseg.children[sidenum_t::WBOTTOM], rseg.children[sidenum_t::WBACK], rseg.children[sidenum_t::WFRONT], csegnum, rcseg.children[sidenum_t::WLEFT], rcseg.children[sidenum_t::WTOP], rcseg.children[sidenum_t::WRIGHT], rcseg.children[sidenum_t::WBOTTOM], rcseg.children[sidenum_t::WBACK], rcseg.children[sidenum_t::WFRONT]);
|
||||
const auto segi = underlying_value(seg.get_unchecked_index());
|
||||
const auto csegi = underlying_value(csegnum);
|
||||
LevelError("Segment #%hu side %u has asymmetric link to segment %hu. Coercing to segment_none; Segments[%hu].children={%hu, %hu, %hu, %hu, %hu, %hu}, Segments[%u].children={%hu, %hu, %hu, %hu, %hu, %hu}.", segi, underlying_value(sidenum), csegi, segi, rseg.children[sidenum_t::WLEFT], rseg.children[sidenum_t::WTOP], rseg.children[sidenum_t::WRIGHT], rseg.children[sidenum_t::WBOTTOM], rseg.children[sidenum_t::WBACK], rseg.children[sidenum_t::WFRONT], csegi, rcseg.children[sidenum_t::WLEFT], rcseg.children[sidenum_t::WTOP], rcseg.children[sidenum_t::WRIGHT], rcseg.children[sidenum_t::WBOTTOM], rcseg.children[sidenum_t::WBACK], rcseg.children[sidenum_t::WFRONT]);
|
||||
rseg.children[sidenum] = segment_none;
|
||||
errors = 1;
|
||||
continue;
|
||||
|
@ -773,7 +774,7 @@ icsegptridx_t find_point_seg(const d_level_shared_segment_state &LevelSharedSegm
|
|||
|
||||
namespace dsx {
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
static inline void add_to_fcd_cache(int seg0, int seg1, int depth, vm_distance dist)
|
||||
static inline void add_to_fcd_cache(segnum_t seg0, segnum_t seg1, int depth, vm_distance dist)
|
||||
{
|
||||
(void)(seg0||seg1||depth||dist);
|
||||
}
|
||||
|
@ -806,7 +807,7 @@ void flush_fcd_cache(void)
|
|||
|
||||
namespace {
|
||||
// ----------------------------------------------------------------------------------------------------------
|
||||
static void add_to_fcd_cache(int seg0, int seg1, int depth, vm_distance dist)
|
||||
static void add_to_fcd_cache(segnum_t seg0, segnum_t seg1, int depth, vm_distance dist)
|
||||
{
|
||||
if (dist > MIN_CACHE_FCD_DIST) {
|
||||
Fcd_cache[Fcd_index].seg0 = seg0;
|
||||
|
@ -1050,7 +1051,7 @@ void create_shortpos_little(const d_level_shared_segment_state &LevelSharedSegme
|
|||
spp.xo = INTEL_SHORT(spp.xo);
|
||||
spp.yo = INTEL_SHORT(spp.yo);
|
||||
spp.zo = INTEL_SHORT(spp.zo);
|
||||
spp.segment = INTEL_SHORT(spp.segment);
|
||||
spp.segment = segnum_t{INTEL_SHORT(underlying_value(spp.segment))};
|
||||
spp.velx = INTEL_SHORT(spp.velx);
|
||||
spp.vely = INTEL_SHORT(spp.vely);
|
||||
spp.velz = INTEL_SHORT(spp.velz);
|
||||
|
@ -1075,7 +1076,7 @@ void extract_shortpos_little(const vmobjptridx_t objp, const shortpos *spp)
|
|||
objp->orient.uvec.z = *sp++ << MATRIX_PRECISION;
|
||||
objp->orient.fvec.z = *sp++ << MATRIX_PRECISION;
|
||||
|
||||
const segnum_t segnum = INTEL_SHORT(spp->segment);
|
||||
const auto segnum = segnum_t{INTEL_SHORT(underlying_value(spp->segment))};
|
||||
|
||||
Assert(segnum <= Highest_segment_index);
|
||||
|
||||
|
@ -1586,7 +1587,7 @@ void validate_segment_all(d_level_shared_segment_state &LevelSharedSegmentState)
|
|||
}
|
||||
|
||||
#if DXX_USE_EDITOR
|
||||
range_for (shared_segment &s, partial_range(Segments, Highest_segment_index + 1, Segments.size()))
|
||||
for (shared_segment &s : partial_range(Segments, Segments.get_count(), Segments.size()))
|
||||
s.segnum = segment_none;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -967,10 +967,10 @@ static ushort netmisc_calc_checksum()
|
|||
do_checksum_calc(reinterpret_cast<uint8_t *>(&t), 4, &sum1, &sum2);
|
||||
}
|
||||
}
|
||||
range_for (auto &j, i.s.children)
|
||||
for (const typename std::underlying_type<segnum_t>::type j : i.s.children)
|
||||
{
|
||||
s = INTEL_SHORT(j);
|
||||
do_checksum_calc(reinterpret_cast<uint8_t *>(&s), 2, &sum1, &sum2);
|
||||
const auto s = INTEL_SHORT(j);
|
||||
do_checksum_calc(reinterpret_cast<const uint8_t *>(&s), 2, &sum1, &sum2);
|
||||
}
|
||||
range_for (const auto vn, i.s.verts)
|
||||
{
|
||||
|
|
|
@ -1659,7 +1659,13 @@ static void multi_do_position(fvmobjptridx &vmobjptridx, const playernum_t pnum,
|
|||
qpp.pos.x = GET_INTEL_INT(&buf[count]); count += 4;
|
||||
qpp.pos.y = GET_INTEL_INT(&buf[count]); count += 4;
|
||||
qpp.pos.z = GET_INTEL_INT(&buf[count]); count += 4;
|
||||
qpp.segment = GET_INTEL_SHORT(&buf[count]); count += 2;
|
||||
if (const auto s = segnum_t{GET_INTEL_SHORT(&buf[count])}; vmsegidx_t::check_nothrow_index(s))
|
||||
{
|
||||
qpp.segment = s;
|
||||
count += 2;
|
||||
}
|
||||
else
|
||||
return;
|
||||
qpp.vel.x = GET_INTEL_INT(&buf[count]); count += 4;
|
||||
qpp.vel.y = GET_INTEL_INT(&buf[count]); count += 4;
|
||||
qpp.vel.z = GET_INTEL_INT(&buf[count]); count += 4;
|
||||
|
@ -2091,7 +2097,6 @@ namespace {
|
|||
|
||||
static void multi_do_door_open(fvmwallptr &vmwallptr, const uint8_t *const buf)
|
||||
{
|
||||
const segnum_t segnum = GET_INTEL_SHORT(&buf[1]);
|
||||
const auto uside = build_sidenum_from_untrusted(buf[3]);
|
||||
if (!uside)
|
||||
return;
|
||||
|
@ -2100,7 +2105,7 @@ static void multi_do_door_open(fvmwallptr &vmwallptr, const uint8_t *const buf)
|
|||
ubyte flag= buf[4];
|
||||
#endif
|
||||
|
||||
const auto &&useg = vmsegptridx.check_untrusted(segnum);
|
||||
const auto &&useg = vmsegptridx.check_untrusted(segnum_t{GET_INTEL_SHORT(&buf[1])});
|
||||
if (!useg)
|
||||
return;
|
||||
const auto &&seg = *useg;
|
||||
|
@ -2173,7 +2178,11 @@ static void multi_do_create_powerup(fvmsegptridx &vmsegptridx, const playernum_t
|
|||
|
||||
count++;
|
||||
powerup_type = buf[count++];
|
||||
const auto &&useg = vmsegptridx.check_untrusted(GET_INTEL_SHORT(&buf[count]));
|
||||
/* Casting the untrusted network input to segnum_t is safe here, since it
|
||||
* is immediately passed to `check_untrusted`, which validates that the
|
||||
* index is reasonable.
|
||||
*/
|
||||
const auto &&useg = vmsegptridx.check_untrusted(segnum_t{GET_INTEL_SHORT(&buf[count])});
|
||||
if (!useg)
|
||||
return;
|
||||
const auto &&segnum = *useg;
|
||||
|
@ -2278,7 +2287,7 @@ static void multi_do_effect_blowup(const playernum_t pnum, const ubyte *buf)
|
|||
|
||||
multi::dispatch->do_protocol_frame(1, 0); // force packets to be sent, ensuring this packet will be attached to following MULTI_TRIGGER
|
||||
|
||||
const auto &&useg = vmsegptridx.check_untrusted(GET_INTEL_SHORT(&buf[2]));
|
||||
const auto &&useg = vmsegptridx.check_untrusted(segnum_t{GET_INTEL_SHORT(&buf[2])});
|
||||
if (!useg)
|
||||
return;
|
||||
const auto uside = build_sidenum_from_untrusted(buf[4]);
|
||||
|
@ -2745,7 +2754,7 @@ void multi_send_position(object &obj)
|
|||
PUT_INTEL_INT(&multibuf[count], qpp.pos.x); count += 4;
|
||||
PUT_INTEL_INT(&multibuf[count], qpp.pos.y); count += 4;
|
||||
PUT_INTEL_INT(&multibuf[count], qpp.pos.z); count += 4;
|
||||
PUT_INTEL_SHORT(&multibuf[count], qpp.segment); count += 2;
|
||||
PUT_INTEL_SEGNUM(&multibuf[count], qpp.segment); count += 2;
|
||||
PUT_INTEL_INT(&multibuf[count], qpp.vel.x); count += 4;
|
||||
PUT_INTEL_INT(&multibuf[count], qpp.vel.y); count += 4;
|
||||
PUT_INTEL_INT(&multibuf[count], qpp.vel.z); count += 4;
|
||||
|
@ -2873,7 +2882,7 @@ void multi_send_door_open(const vcsegidx_t segnum, const sidenum_t side, const w
|
|||
{
|
||||
multi_command<MULTI_DOOR_OPEN> multibuf;
|
||||
// When we open a door make sure everyone else opens that door
|
||||
PUT_INTEL_SHORT(&multibuf[1], segnum );
|
||||
PUT_INTEL_SEGNUM(&multibuf[1], segnum);
|
||||
multibuf[3] = underlying_value(side);
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
(void)flag;
|
||||
|
@ -2892,7 +2901,7 @@ void multi_send_door_open_specific(const playernum_t pnum, const vcsegidx_t segn
|
|||
// Assert (pnum>-1 && pnum<N_players);
|
||||
|
||||
multi_command<MULTI_DOOR_OPEN> multibuf;
|
||||
PUT_INTEL_SHORT(&multibuf[1], segnum);
|
||||
PUT_INTEL_SEGNUM(&multibuf[1], segnum);
|
||||
multibuf[3] = static_cast<int8_t>(side);
|
||||
multibuf[4] = underlying_value(flag);
|
||||
|
||||
|
@ -2966,7 +2975,7 @@ void multi_send_create_powerup(const powerup_type_t powerup_type, const vcsegidx
|
|||
multi_command<MULTI_CREATE_POWERUP> multibuf;
|
||||
multibuf[count] = Player_num; count += 1;
|
||||
multibuf[count] = powerup_type; count += 1;
|
||||
PUT_INTEL_SHORT(&multibuf[count], segnum ); count += 2;
|
||||
PUT_INTEL_SEGNUM(&multibuf[count], segnum); count += 2;
|
||||
PUT_INTEL_SHORT(&multibuf[count], objnum ); count += 2;
|
||||
if constexpr (words_bigendian)
|
||||
{
|
||||
|
@ -3094,7 +3103,7 @@ void multi_send_effect_blowup(const vcsegidx_t segnum, const sidenum_t side, con
|
|||
count += 1;
|
||||
multi_command<MULTI_EFFECT_BLOWUP> multibuf;
|
||||
multibuf[count] = Player_num; count += 1;
|
||||
PUT_INTEL_SHORT(&multibuf[count], segnum); count += 2;
|
||||
PUT_INTEL_SEGNUM(&multibuf[count], segnum); count += 2;
|
||||
multibuf[count] = static_cast<int8_t>(side); count += 1;
|
||||
PUT_INTEL_INT(&multibuf[count], pnt.x); count += 4;
|
||||
PUT_INTEL_INT(&multibuf[count], pnt.y); count += 4;
|
||||
|
@ -4132,7 +4141,7 @@ void multi_send_light_specific (const playernum_t pnum, const vcsegptridx_t segn
|
|||
// Assert (pnum>-1 && pnum<N_players);
|
||||
|
||||
multi_command<MULTI_LIGHT> multibuf;
|
||||
PUT_INTEL_SHORT(&multibuf[count], segnum);
|
||||
PUT_INTEL_SEGNUM(&multibuf[count], segnum);
|
||||
count += sizeof(uint16_t);
|
||||
multibuf[count] = underlying_value(val); count++;
|
||||
|
||||
|
@ -4150,8 +4159,7 @@ static void multi_do_light (const ubyte *buf)
|
|||
{
|
||||
const auto sides = buf[3];
|
||||
|
||||
const segnum_t seg = GET_INTEL_SHORT(&buf[1]);
|
||||
const auto &&usegp = vmsegptridx.check_untrusted(seg);
|
||||
const auto &&usegp = vmsegptridx.check_untrusted(segnum_t{GET_INTEL_SHORT(&buf[1])});
|
||||
if (!usegp)
|
||||
return;
|
||||
const auto &&segp = *usegp;
|
||||
|
@ -6110,7 +6118,10 @@ void multi_object_rw_to_object(const object_rw *const obj_rw, object &obj)
|
|||
obj.render_type = RT_NONE;
|
||||
}
|
||||
obj.flags = obj_rw->flags;
|
||||
obj.segnum = obj_rw->segnum;
|
||||
{
|
||||
const auto s = segnum_t{obj_rw->segnum};
|
||||
obj.segnum = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
/* obj->attached_obj cleared by caller */
|
||||
obj.pos = obj_rw->pos;
|
||||
obj.orient = obj_rw->orient;
|
||||
|
@ -6196,7 +6207,10 @@ void multi_object_rw_to_object(const object_rw *const obj_rw, object &obj)
|
|||
obj.ctype.ai_info.SKIP_AI_COUNT = obj_rw->ctype.ai_info.flags[7];
|
||||
obj.ctype.ai_info.REMOTE_OWNER = obj_rw->ctype.ai_info.flags[8];
|
||||
obj.ctype.ai_info.REMOTE_SLOT_NUM = obj_rw->ctype.ai_info.flags[9];
|
||||
obj.ctype.ai_info.hide_segment = obj_rw->ctype.ai_info.hide_segment;
|
||||
{
|
||||
const auto s = segnum_t{obj_rw->ctype.ai_info.hide_segment};
|
||||
obj.ctype.ai_info.hide_segment = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
obj.ctype.ai_info.hide_index = obj_rw->ctype.ai_info.hide_index;
|
||||
obj.ctype.ai_info.path_length = obj_rw->ctype.ai_info.path_length;
|
||||
obj.ctype.ai_info.cur_path_index = obj_rw->ctype.ai_info.cur_path_index;
|
||||
|
|
|
@ -478,7 +478,7 @@ void multi_send_robot_position_sub(const vmobjptridx_t objnum, int now)
|
|||
PUT_INTEL_INT(&multibuf[loc], qpp.pos.x); loc += 4;
|
||||
PUT_INTEL_INT(&multibuf[loc], qpp.pos.y); loc += 4;
|
||||
PUT_INTEL_INT(&multibuf[loc], qpp.pos.z); loc += 4;
|
||||
PUT_INTEL_SHORT(&multibuf[loc], qpp.segment); loc += 2;
|
||||
PUT_INTEL_SEGNUM(&multibuf[loc], qpp.segment); loc += 2;
|
||||
PUT_INTEL_INT(&multibuf[loc], qpp.vel.x); loc += 4;
|
||||
PUT_INTEL_INT(&multibuf[loc], qpp.vel.y); loc += 4;
|
||||
PUT_INTEL_INT(&multibuf[loc], qpp.vel.z); loc += 4;
|
||||
|
@ -707,7 +707,7 @@ static void multi_send_create_robot_powerups(const object_base &del_obj)
|
|||
multibuf[loc] = del_obj.contains_count; loc += 1;
|
||||
multibuf[loc] = del_obj.contains_type; loc += 1;
|
||||
multibuf[loc] = del_obj.contains_id; loc += 1;
|
||||
PUT_INTEL_SHORT(&multibuf[loc], del_obj.segnum); loc += 2;
|
||||
PUT_INTEL_SEGNUM(&multibuf[loc], del_obj.segnum); loc += 2;
|
||||
if constexpr (words_bigendian)
|
||||
{
|
||||
vms_vector swapped_vec;
|
||||
|
@ -836,7 +836,7 @@ void multi_do_robot_position(const playernum_t pnum, const ubyte *buf)
|
|||
if ((robot->type != OBJ_ROBOT) || (robot->flags & OF_EXPLODING)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (robot->ctype.ai_info.REMOTE_OWNER != pnum)
|
||||
{
|
||||
if (robot->ctype.ai_info.REMOTE_OWNER == -1)
|
||||
|
@ -866,7 +866,13 @@ void multi_do_robot_position(const playernum_t pnum, const ubyte *buf)
|
|||
qpp.pos.x = GET_INTEL_INT(&buf[loc]); loc += 4;
|
||||
qpp.pos.y = GET_INTEL_INT(&buf[loc]); loc += 4;
|
||||
qpp.pos.z = GET_INTEL_INT(&buf[loc]); loc += 4;
|
||||
qpp.segment = GET_INTEL_SHORT(&buf[loc]); loc += 2;
|
||||
if (const auto s = segnum_t{GET_INTEL_SHORT(&buf[loc])}; vmsegidx_t::check_nothrow_index(s))
|
||||
{
|
||||
qpp.segment = s;
|
||||
loc += 2;
|
||||
}
|
||||
else
|
||||
return;
|
||||
qpp.vel.x = GET_INTEL_INT(&buf[loc]); loc += 4;
|
||||
qpp.vel.y = GET_INTEL_INT(&buf[loc]); loc += 4;
|
||||
qpp.vel.z = GET_INTEL_INT(&buf[loc]); loc += 4;
|
||||
|
@ -1250,7 +1256,9 @@ void multi_do_create_robot_powerups(const playernum_t pnum, const ubyte *buf)
|
|||
uint8_t contains_count = buf[loc]; loc += 1;
|
||||
uint8_t contains_type = buf[loc]; loc += 1;
|
||||
uint8_t contains_id = buf[loc]; loc += 1;
|
||||
segnum_t segnum = GET_INTEL_SHORT(buf + loc); loc += 2;
|
||||
const auto segnum = segnum_t{GET_INTEL_SHORT(&buf[loc])}; loc += 2;
|
||||
if (!vmsegidx_t::check_nothrow_index(segnum))
|
||||
return;
|
||||
vms_vector pos;
|
||||
memcpy(&pos, &buf[loc], sizeof(pos)); loc += 12;
|
||||
|
||||
|
|
|
@ -5661,7 +5661,7 @@ void net_udp_send_pdata()
|
|||
PUT_INTEL_INT(&buf[len], qpp.pos.x); len += 4;
|
||||
PUT_INTEL_INT(&buf[len], qpp.pos.y); len += 4;
|
||||
PUT_INTEL_INT(&buf[len], qpp.pos.z); len += 4;
|
||||
PUT_INTEL_SHORT(&buf[len], qpp.segment); len += 2;
|
||||
PUT_INTEL_SEGNUM(&buf[len], qpp.segment); len += 2;
|
||||
PUT_INTEL_INT(&buf[len], qpp.vel.x); len += 4;
|
||||
PUT_INTEL_INT(&buf[len], qpp.vel.y); len += 4;
|
||||
PUT_INTEL_INT(&buf[len], qpp.vel.z); len += 4;
|
||||
|
@ -5710,7 +5710,13 @@ void net_udp_process_pdata(const uint8_t *data, uint_fast32_t data_len, const _s
|
|||
pd.qpp.pos.x = GET_INTEL_INT(&data[len]); len += 4;
|
||||
pd.qpp.pos.y = GET_INTEL_INT(&data[len]); len += 4;
|
||||
pd.qpp.pos.z = GET_INTEL_INT(&data[len]); len += 4;
|
||||
pd.qpp.segment = GET_INTEL_SHORT(&data[len]); len += 2;
|
||||
if (const auto s = segnum_t{GET_INTEL_SHORT(&data[len])}; vmsegidx_t::check_nothrow_index(s))
|
||||
{
|
||||
len += 2;
|
||||
pd.qpp.segment = s;
|
||||
}
|
||||
else
|
||||
return;
|
||||
pd.qpp.vel.x = GET_INTEL_INT(&data[len]); len += 4;
|
||||
pd.qpp.vel.y = GET_INTEL_INT(&data[len]); len += 4;
|
||||
pd.qpp.vel.z = GET_INTEL_INT(&data[len]); len += 4;
|
||||
|
|
|
@ -446,9 +446,9 @@ static void nd_read_short(uint16_t *const s)
|
|||
|
||||
static void nd_read_segnum16(segnum_t &s)
|
||||
{
|
||||
short i;
|
||||
uint16_t i;
|
||||
nd_read_short(&i);
|
||||
s = i;
|
||||
s = segnum_t{i};
|
||||
}
|
||||
|
||||
static void nd_read_objnum16(objnum_t &o)
|
||||
|
@ -476,9 +476,9 @@ static void nd_read_int(unsigned *i)
|
|||
|
||||
static void nd_read_segnum32(segnum_t &s)
|
||||
{
|
||||
int i;
|
||||
int32_t i;
|
||||
nd_read_int(&i);
|
||||
s = i;
|
||||
s = segnum_t{static_cast<uint16_t>(i)};
|
||||
}
|
||||
|
||||
static void nd_read_objnum32(objnum_t &o)
|
||||
|
@ -550,7 +550,7 @@ static void nd_read_shortpos(object_base &obj)
|
|||
nd_read_short(&sp.xo);
|
||||
nd_read_short(&sp.yo);
|
||||
nd_read_short(&sp.zo);
|
||||
nd_read_short(&sp.segment);
|
||||
nd_read_segnum16(sp.segment);
|
||||
nd_read_short(&sp.velx);
|
||||
nd_read_short(&sp.vely);
|
||||
nd_read_short(&sp.velz);
|
||||
|
@ -2162,7 +2162,7 @@ static int newdemo_read_frame_information(int rewrite)
|
|||
// HACK HACK HACK -- the viewer to segment 0 for bogus view.
|
||||
|
||||
if (segnum > Highest_segment_index)
|
||||
segnum = 0;
|
||||
segnum = {};
|
||||
obj_link_unchecked(Objects.vmptr, viewer_vmobj, Segments.vmptridx(segnum));
|
||||
}
|
||||
}
|
||||
|
@ -2822,12 +2822,13 @@ static int newdemo_read_frame_information(int rewrite)
|
|||
|
||||
|
||||
case ND_EVENT_WALL_SET_TMAP_NUM1: {
|
||||
uint16_t seg, cseg, tmap;
|
||||
segnum_t seg, cseg;
|
||||
uint16_t tmap;
|
||||
uint8_t side, cside;
|
||||
|
||||
nd_read_short(&seg);
|
||||
nd_read_segnum16(seg);
|
||||
nd_read_byte(&side);
|
||||
nd_read_short(&cseg);
|
||||
nd_read_segnum16(cseg);
|
||||
nd_read_byte(&cside);
|
||||
nd_read_short( &tmap );
|
||||
if (rewrite)
|
||||
|
@ -2845,12 +2846,13 @@ static int newdemo_read_frame_information(int rewrite)
|
|||
}
|
||||
|
||||
case ND_EVENT_WALL_SET_TMAP_NUM2: {
|
||||
uint16_t seg, cseg, tmap;
|
||||
segnum_t seg, cseg;
|
||||
uint16_t tmap;
|
||||
uint8_t side, cside;
|
||||
|
||||
nd_read_short(&seg);
|
||||
nd_read_segnum16(seg);
|
||||
nd_read_byte(&side);
|
||||
nd_read_short(&cseg);
|
||||
nd_read_segnum16(cseg);
|
||||
nd_read_byte(&cside);
|
||||
nd_read_short( &tmap );
|
||||
if (rewrite)
|
||||
|
|
|
@ -63,7 +63,10 @@ namespace dsx {
|
|||
*/
|
||||
void delta_light_read(delta_light *dl, PHYSFS_File *fp)
|
||||
{
|
||||
dl->segnum = PHYSFSX_readShort(fp);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(fp))};
|
||||
dl->segnum = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
dl->sidenum = build_sidenum_from_untrusted(PHYSFSX_readByte(fp)).value_or(sidenum_t::WLEFT);
|
||||
PHYSFSX_readByte(fp);
|
||||
dl->vert_light[side_relative_vertnum::_0] = PHYSFSX_readByte(fp);
|
||||
|
@ -78,7 +81,10 @@ void delta_light_read(delta_light *dl, PHYSFS_File *fp)
|
|||
*/
|
||||
void dl_index_read(dl_index *di, PHYSFS_File *fp)
|
||||
{
|
||||
di->segnum = PHYSFSX_readShort(fp);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(fp))};
|
||||
di->segnum = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
di->sidenum = build_sidenum_from_untrusted(PHYSFSX_readByte(fp)).value_or(sidenum_t::WLEFT);
|
||||
di->count = PHYSFSX_readByte(fp);
|
||||
di->index = PHYSFSX_readShort(fp);
|
||||
|
|
|
@ -524,7 +524,10 @@ static void state_object_rw_to_object(const object_rw *const obj_rw, object &obj
|
|||
obj.render_type = RT_NONE;
|
||||
}
|
||||
obj.flags = obj_rw->flags;
|
||||
obj.segnum = obj_rw->segnum;
|
||||
{
|
||||
const auto s = segnum_t{obj_rw->segnum};
|
||||
obj.segnum = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
obj.attached_obj = obj_rw->attached_obj;
|
||||
obj.pos.x = obj_rw->pos.x;
|
||||
obj.pos.y = obj_rw->pos.y;
|
||||
|
@ -617,7 +620,10 @@ static void state_object_rw_to_object(const object_rw *const obj_rw, object &obj
|
|||
obj.ctype.ai_info.SKIP_AI_COUNT = obj_rw->ctype.ai_info.flags[7];
|
||||
obj.ctype.ai_info.REMOTE_OWNER = obj_rw->ctype.ai_info.flags[8];
|
||||
obj.ctype.ai_info.REMOTE_SLOT_NUM = obj_rw->ctype.ai_info.flags[9];
|
||||
obj.ctype.ai_info.hide_segment = obj_rw->ctype.ai_info.hide_segment;
|
||||
{
|
||||
const auto s = segnum_t{obj_rw->ctype.ai_info.hide_segment};
|
||||
obj.ctype.ai_info.hide_segment = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
obj.ctype.ai_info.hide_index = obj_rw->ctype.ai_info.hide_index;
|
||||
obj.ctype.ai_info.path_length = obj_rw->ctype.ai_info.path_length;
|
||||
obj.ctype.ai_info.cur_path_index = obj_rw->ctype.ai_info.cur_path_index;
|
||||
|
|
|
@ -593,7 +593,10 @@ void v26_trigger_read(PHYSFS_File *fp, trigger &t)
|
|||
t.value = PHYSFSX_readInt(fp);
|
||||
PHYSFSX_readInt(fp);
|
||||
for (unsigned i=0; i < MAX_WALLS_PER_LINK; i++ )
|
||||
t.seg[i] = PHYSFSX_readShort(fp);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(fp))};
|
||||
t.seg[i] = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
for (unsigned i=0; i < MAX_WALLS_PER_LINK; i++ )
|
||||
{
|
||||
auto s = build_sidenum_from_untrusted(PHYSFSX_readShort(fp));
|
||||
|
@ -617,7 +620,10 @@ void v29_trigger_read(v29_trigger *t, PHYSFS_File *fp)
|
|||
PHYSFSX_readByte(fp);
|
||||
t->num_links = PHYSFSX_readShort(fp);
|
||||
for (unsigned i=0; i<MAX_WALLS_PER_LINK; i++ )
|
||||
t->seg[i] = PHYSFSX_readShort(fp);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(fp))};
|
||||
t->seg[i] = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
for (unsigned i=0; i<MAX_WALLS_PER_LINK; i++ )
|
||||
{
|
||||
auto s = build_sidenum_from_untrusted(PHYSFSX_readShort(fp));
|
||||
|
@ -637,7 +643,10 @@ extern void v30_trigger_read(v30_trigger *t, PHYSFS_File *fp)
|
|||
t->value = PHYSFSX_readFix(fp);
|
||||
PHYSFSX_readFix(fp);
|
||||
for (unsigned i=0; i<MAX_WALLS_PER_LINK; i++ )
|
||||
t->seg[i] = PHYSFSX_readShort(fp);
|
||||
{
|
||||
const auto s = segnum_t{static_cast<uint16_t>(PHYSFSX_readShort(fp))};
|
||||
t->seg[i] = vmsegidx_t::check_nothrow_index(s) ? s : segment_none;
|
||||
}
|
||||
for (unsigned i=0; i<MAX_WALLS_PER_LINK; i++ )
|
||||
t->side[i] = build_sidenum_from_untrusted(PHYSFSX_readShort(fp)).value_or(sidenum_t::WLEFT);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue