diff --git a/common/main/fwd-segment.h b/common/main/fwd-segment.h index 211081d13..85b067b64 100644 --- a/common/main/fwd-segment.h +++ b/common/main/fwd-segment.h @@ -161,7 +161,8 @@ constexpr std::integral_constant MAX_DELTA_LIGHTS{}; // Orig constexpr std::integral_constant DL_SCALE{}; // Divide light to allow 3 bits integer, 5 bits fraction. -using d_delta_light_array = std::array; +enum class delta_light_index : uint16_t; +using d_delta_light_array = enumerated_array; void clear_light_subtracted(); diff --git a/common/main/segment.h b/common/main/segment.h index f2692aed2..9864991ed 100644 --- a/common/main/segment.h +++ b/common/main/segment.h @@ -396,6 +396,10 @@ struct shared_side::illegal_type : std::runtime_error namespace dsx { #if defined(DXX_BUILD_DESCENT_II) +enum class delta_light_index : uint16_t +{ +}; + // New stuff, 10/14/95: For shooting out lights and monitors. // Light cast upon vert_light vertices in segnum:sidenum by some light struct delta_light : prohibit_void_ptr @@ -410,7 +414,7 @@ struct dl_index { segnum_t segnum; sidenum_t sidenum; uint8_t count; - uint16_t index; + delta_light_index index; constexpr std::strong_ordering operator<=>(const dl_index &rhs) const { if (const auto r = segnum <=> rhs.segnum; r != std::strong_ordering::equal) diff --git a/similar/main/gameseg.cpp b/similar/main/gameseg.cpp index a6e52339f..629cc2de3 100644 --- a/similar/main/gameseg.cpp +++ b/similar/main/gameseg.cpp @@ -1733,12 +1733,12 @@ static void change_light(const d_level_shared_destructible_light_state &LevelSha const fix ds = dir * DL_SCALE; auto &Dl_indices = LevelSharedDestructibleLightState.Dl_indices; const auto &&pr = cast_range_result(Dl_indices.vcptr); - const auto &&er = std::equal_range(pr.begin(), pr.end(), dl_index{segnum, sidenum, 0, 0}); + const auto &&er = std::equal_range(pr.begin(), pr.end(), dl_index{segnum, sidenum, 0, {}}); auto &Delta_lights = LevelSharedDestructibleLightState.Delta_lights; range_for (auto &i, partial_range_t(er.first.base().base(), er.second.base().base())) { - const uint_fast32_t idx = i.index; - range_for (auto &j, partial_const_range(Delta_lights, idx, idx + i.count)) + const std::size_t idx = underlying_value(i.index); + for (auto &j : partial_const_range(Delta_lights, idx, idx + i.count)) { assert(j.sidenum < MAX_SIDES_PER_SEGMENT); const auto &&segp = vmsegptr(j.segnum); diff --git a/similar/main/segment.cpp b/similar/main/segment.cpp index 1c18be99d..f93409d30 100644 --- a/similar/main/segment.cpp +++ b/similar/main/segment.cpp @@ -58,6 +58,14 @@ void segment_side_wall_tmap_write(PHYSFS_File *fp, const shared_side &sside, con #if defined(DXX_BUILD_DESCENT_II) namespace dsx { +static std::optional build_delta_light_index_from_untrusted(const uint16_t i) +{ + if (i < MAX_DELTA_LIGHTS) + return delta_light_index{i}; + else + return std::nullopt; +} + /* * reads a delta_light structure from a PHYSFS_File */ @@ -86,8 +94,17 @@ void dl_index_read(dl_index *di, PHYSFS_File *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); + const auto count = PHYSFSX_readByte(fp); + if (const auto i = build_delta_light_index_from_untrusted(PHYSFSX_readShort(fp)); i) + { + di->count = count; + di->index = *i; + } + else + { + di->count = 0; + di->index = {}; + } } void segment2_write(const cscusegment s2, PHYSFS_File *fp) @@ -115,7 +132,7 @@ void dl_index_write(const dl_index *di, PHYSFS_File *fp) PHYSFS_writeSLE16(fp, di->segnum); PHYSFSX_writeU8(fp, underlying_value(di->sidenum)); PHYSFSX_writeU8(fp, di->count); - PHYSFS_writeSLE16(fp, di->index); + PHYSFS_writeSLE16(fp, underlying_value(di->index)); } }