diff --git a/common/include/dxxerror.h b/common/include/dxxerror.h index fbc01a051..4c301c618 100644 --- a/common/include/dxxerror.h +++ b/common/include/dxxerror.h @@ -75,7 +75,8 @@ void UserError(const char *fmt, ...) __noreturn __attribute_format_printf(1, 2); #define UserError(F,...) dxx_call_printf_checked(UserError,(UserError_puts),(),DXX_STRINGIZE_FL(__FILE__, __LINE__, F),##__VA_ARGS__) #define Assert assert -#define LevelError(F,...) con_printf(CON_URGENT, DXX_STRINGIZE_FL(__FILE__, __LINE__, F " Please report this to the level author, not to the Rebirth maintainers."), ##__VA_ARGS__) +#define LevelErrorV(V,F,...) con_printf(V, DXX_STRINGIZE_FL(__FILE__, __LINE__, F " Please report this to the level author, not to the Rebirth maintainers."), ##__VA_ARGS__) +#define LevelError(F,...) LevelErrorV(CON_URGENT, F, ##__VA_ARGS__) /* Compatibility with x86-specific name */ #define Int3() d_debugbreak() diff --git a/d1x-rebirth/CHANGELOG.txt b/d1x-rebirth/CHANGELOG.txt index 136f1647d..c13db2da5 100644 --- a/d1x-rebirth/CHANGELOG.txt +++ b/d1x-rebirth/CHANGELOG.txt @@ -2182,7 +2182,7 @@ main/songs.c: start at track 1 and continue playing audio CD if it's not the ori 20080615 -------- -main/gameseq.c, main/mission.c, main/newdemo.c, main/scores.c: Fixed scores write (wasn't PhysFS); Fixed PLAYING_BUILTING_MISSION in D1X; Better call for DoJasonInterpolate in demo code (hopefully) +main/gameseq.c, main/mission.c, main/newdemo.c, main/scores.c: Fixed scores write (wasn't PhysFS); Fixed PLAYING_BUILTIN_MISSION in D1X; Better call for DoJasonInterpolate in demo code (hopefully) arch/sdl/digi_mixer.c, arch/sdl/rbaudio.c, include/inferno.h, include/rbaudio.h, main/game.c, main/songs.c: tidy up music keys, ALT-SHIFT-F9 ejects audio CDs 20080612 diff --git a/similar/main/gameseg.cpp b/similar/main/gameseg.cpp index d8d20de58..29404b197 100644 --- a/similar/main/gameseg.cpp +++ b/similar/main/gameseg.cpp @@ -39,7 +39,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #include "gameseq.h" #include "wall.h" #include "fuelcen.h" -#include "bm.h" +#include "textures.h" #include "fvi.h" #include "object.h" #include "byteutil.h" @@ -1230,22 +1230,17 @@ static int check_for_degenerate_segment(const vcsegptr_t sp) } -static void add_side_as_quad(const vsegptr_t sp, int sidenum, const vms_vector &normal) +static void add_side_as_quad(side *const sidep, const vms_vector &normal) { - side *sidep = &sp->sides[sidenum]; - sidep->set_type(SIDE_IS_QUAD); - sidep->normals[0] = normal; sidep->normals[1] = normal; - // If there is a connection here, we only formed the faces for the purpose of determining segment boundaries, // so don't generate polys, else they will get rendered. // if (sp->children[sidenum] != -1) // sidep->render_flag = 0; // else // sidep->render_flag = 1; - } } @@ -1401,7 +1396,7 @@ void create_walls_on_side(const vsegptridx_t sp, int sidenum) vm_vec_negate(vn); if (dist_to_plane <= PLANE_DIST_TOLERANCE) - add_side_as_quad(sp, sidenum, vn); + add_side_as_quad(&sp->sides[sidenum], vn); else { add_side_as_2_triangles(sp, sidenum); @@ -1438,28 +1433,82 @@ void create_walls_on_side(const vsegptridx_t sp, int sidenum) } - - -// ------------------------------------------------------------------------------- -static void validate_removable_wall(const vsegptridx_t sp, int sidenum, int tmap_num) -{ - create_walls_on_side(sp, sidenum); - - sp->sides[sidenum].tmap_num = tmap_num; - -// assign_default_uvs_to_side(sp, sidenum); -// assign_light_to_side(sp, sidenum); -} - // ------------------------------------------------------------------------------- // Make a just-modified segment side valid. void validate_segment_side(const vsegptridx_t sp, int sidenum) { - if (sp->sides[sidenum].wall_num == wall_none) + auto &side = sp->sides[sidenum]; + const auto old_tmap_num = side.tmap_num; create_walls_on_side(sp, sidenum); - else // create_removable_wall(sp, sidenum, sp->sides[sidenum].tmap_num); - validate_removable_wall(sp, sidenum, sp->sides[sidenum].tmap_num); + /* If the texture is correct, put it back. This is sometimes a + * wasted store, but never harmful. + * + * If the texture was wrong, fix it, and log a diagnostic. For + * builtin missions, log the diagnostic at level CON_VERBOSE, since + * retail levels trigger this during normal play. For external + * missions, log the diagnostic at level CON_URGENT. External + * levels might be fixable by contacting the author, but the retail + * levels can only be fixed by using a Rebirth level patch file (not + * supported yet). When fixing the texture, change it to 0 for + * walls and 1 for non-walls. This should make walls transparent + * for their primary texture; transparent non-walls usually generate + * ugly visual artifacts, so choose a non-zero texture for them. + * + * Known affected retail levels (incomplete list): + +Descent 2: Counterstrike +sha256: f1abf516512739c97b43e2e93611a2398fc9f8bc7a014095ebc2b6b2fd21b703 descent2.hog +Levels 1-3: clean + +Level #4 +segment #170 side #4 has invalid tmap 910 (NumTextures=910) +segment #171 side #5 has invalid tmap 910 (NumTextures=910) +segment #184 side #2 has invalid tmap 910 (NumTextures=910) +segment #188 side #5 has invalid tmap 910 (NumTextures=910) + +Level #5 +segment #141 side #4 has invalid tmap 910 (NumTextures=910) + +Level #6 +segment #128 side #4 has invalid tmap 910 (NumTextures=910) + +Level #7 +segment #26 side #5 has invalid tmap 910 (NumTextures=910) +segment #28 side #5 has invalid tmap 910 (NumTextures=910) +segment #60 side #5 has invalid tmap 910 (NumTextures=910) +segment #63 side #5 has invalid tmap 910 (NumTextures=910) +segment #161 side #4 has invalid tmap 910 (NumTextures=910) +segment #305 side #4 has invalid tmap 910 (NumTextures=910) +segment #427 side #4 has invalid tmap 910 (NumTextures=910) +segment #533 side #5 has invalid tmap 910 (NumTextures=910) +segment #536 side #4 has invalid tmap 910 (NumTextures=910) +segment #647 side #4 has invalid tmap 910 (NumTextures=910) +segment #648 side #5 has invalid tmap 910 (NumTextures=910) + +Level #8 +segment #0 side #4 has invalid tmap 910 (NumTextures=910) +segment #92 side #0 has invalid tmap 910 (NumTextures=910) +segment #92 side #5 has invalid tmap 910 (NumTextures=910) +segment #94 side #1 has invalid tmap 910 (NumTextures=910) +segment #94 side #2 has invalid tmap 910 (NumTextures=910) +segment #95 side #0 has invalid tmap 910 (NumTextures=910) +segment #95 side #1 has invalid tmap 910 (NumTextures=910) +segment #97 side #5 has invalid tmap 910 (NumTextures=910) +segment #98 side #3 has invalid tmap 910 (NumTextures=910) +segment #100 side #1 has invalid tmap 910 (NumTextures=910) +segment #102 side #1 has invalid tmap 910 (NumTextures=910) +segment #104 side #3 has invalid tmap 910 (NumTextures=910) + +Levels 9-end: unchecked + + */ + side.tmap_num = old_tmap_num < NumTextures + ? old_tmap_num + : ( + LevelErrorV(PLAYING_BUILTIN_MISSION ? CON_VERBOSE : CON_URGENT, "segment #%hu side #%i has invalid tmap %u (NumTextures=%u).", static_cast(sp), sidenum, old_tmap_num, NumTextures), + (side.wall_num == wall_none) + ); // Set render_flag. // If side doesn't have a child, then render wall. If it does have a child, but there is a temporary diff --git a/similar/main/render.cpp b/similar/main/render.cpp index 3b98a2ee2..7cdcb4e26 100644 --- a/similar/main/render.cpp +++ b/similar/main/render.cpp @@ -220,7 +220,7 @@ static inline int is_alphablend_eclip(int eclip_num) // vp is a pointer to vertex ids. // tmap1, tmap2 are texture map ids. tmap2 is the pasty one. namespace dsx { -static void render_face(const vcsegptridx_t segp, int sidenum, unsigned nv, const array &vp, int tmap1, int tmap2, array uvl_copy, WALL_IS_DOORWAY_result_t wid_flags) +static void render_face(const segment &segp, const unsigned sidenum, const unsigned nv, const array &vp, const int tmap1, const int tmap2, array uvl_copy, const WALL_IS_DOORWAY_result_t wid_flags) { grs_bitmap *bm; @@ -241,8 +241,7 @@ static void render_face(const vcsegptridx_t segp, int sidenum, unsigned nv, cons #elif defined(DXX_BUILD_DESCENT_II) //handle cloaked walls if (wid_flags & WID_CLOAKED_FLAG) { - auto wall_num = segp->sides[sidenum].wall_num; - Assert(wall_num != wall_none); + const auto wall_num = segp.sides[sidenum].wall_num; gr_settransblend(vcwallptr(wall_num)->cloak_value, GR_BLEND_NORMAL); const uint8_t color = BM_XRGB(0, 0, 0); // set to black (matters for s3) @@ -256,7 +255,6 @@ static void render_face(const vcsegptridx_t segp, int sidenum, unsigned nv, cons if (tmap1 >= NumTextures) { Int3(); - return; } #if DXX_USE_OGL @@ -370,7 +368,7 @@ static void render_face(const vcsegptridx_t segp, int sidenum, unsigned nv, cons // ---------------------------------------------------------------------------- // Only called if editor active. // Used to determine which face was clicked on. -static void check_face(segnum_t segnum, int sidenum, int facenum, unsigned nv, const array &vp, int tmap1, int tmap2, const array &uvl_copy) +static void check_face(const vsegidx_t segnum, const unsigned sidenum, const unsigned facenum, const unsigned nv, const array &vp, const int tmap1, const int tmap2, const array &uvl_copy) { #if DXX_USE_EDITOR if (_search_mode) { @@ -435,7 +433,7 @@ static void check_face(segnum_t segnum, int sidenum, int facenum, unsigned nv, c } template -static inline void check_render_face(index_sequence, const vcsegptridx_t segnum, int sidenum, unsigned facenum, const array &ovp, int tmap1, int tmap2, const array &uvlp, WALL_IS_DOORWAY_result_t wid_flags, const std::size_t nv) +static inline void check_render_face(index_sequence, const vcsegptridx_t segnum, const unsigned sidenum, const unsigned facenum, const array &ovp, const int tmap1, const int tmap2, const array &uvlp, const WALL_IS_DOORWAY_result_t wid_flags, const std::size_t nv) { const array vp{{ovp[N]...}}; const array uvl_copy{{ @@ -446,7 +444,7 @@ static inline void check_render_face(index_sequence, const vcsegptridx_t s } template -static inline void check_render_face(index_sequence is, const vcsegptridx_t segnum, int sidenum, unsigned facenum, const array &vp, int tmap1, int tmap2, const array &uvlp, WALL_IS_DOORWAY_result_t wid_flags) +static inline void check_render_face(index_sequence is, const vcsegptridx_t segnum, const unsigned sidenum, const unsigned facenum, const array &vp, const int tmap1, const int tmap2, const array &uvlp, const WALL_IS_DOORWAY_result_t wid_flags) { check_render_face(is, segnum, sidenum, facenum, vp, tmap1, tmap2, uvlp, wid_flags, 4); } @@ -455,7 +453,7 @@ static inline void check_render_face(index_sequence is, const vc * are default constructed, gcc zero initializes all members. */ template -static inline void check_render_face(index_sequence, const vcsegptridx_t segnum, int sidenum, unsigned facenum, const array &vp, int tmap1, int tmap2, const array &uvlp, WALL_IS_DOORWAY_result_t wid_flags) +static inline void check_render_face(index_sequence, const vcsegptridx_t segnum, const unsigned sidenum, const unsigned facenum, const array &vp, const int tmap1, const int tmap2, const array &uvlp, const WALL_IS_DOORWAY_result_t wid_flags) { check_render_face(index_sequence(), segnum, sidenum, facenum, vp, tmap1, tmap2, uvlp, wid_flags, 3); }