From 895fb719d98407d6eecd97bc258b5575327a8272 Mon Sep 17 00:00:00 2001 From: nukeykt Date: Mon, 23 Sep 2019 04:26:07 +0900 Subject: [PATCH] blooddemohack -> enginecompatibility_mode --- source/blood/src/blood.cpp | 2 +- source/build/include/build.h | 13 +- source/build/src/clip.cpp | 234 +++++++++++++++++++++++++-------- source/build/src/common.cpp | 3 +- source/build/src/engine.cpp | 120 +++++++++++++++-- source/build/src/engine_priv.h | 19 ++- source/rr/src/game.cpp | 2 +- 7 files changed, 318 insertions(+), 75 deletions(-) diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index a8c32a294..2bf999b0e 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -592,7 +592,7 @@ void StartLevel(GAMEOPTIONS *gameOptions) } } bVanilla = gDemo.at1 && gDemo.m_bLegacy; - blooddemohack = 2;//bVanilla; + enginecompatibility_mode = ENGINECOMPATIBILITY_19960925;//bVanilla; memset(xsprite,0,sizeof(xsprite)); memset(sprite,0,kMaxSprites*sizeof(spritetype)); drawLoadingScreen(); diff --git a/source/build/include/build.h b/source/build/include/build.h index f21553e07..74cb4f070 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -935,7 +935,14 @@ static FORCE_INLINE int32_t videoGetRenderMode(void) } extern int32_t bloodhack; -extern int32_t blooddemohack; +enum { + ENGINECOMPATIBILITY_NONE = 0, + ENGINECOMPATIBILITY_19950829, // Powerslave/Exhumed + ENGINECOMPATIBILITY_19960925, // Blood v1.21 + ENGINECOMPATIBILITY_19961112, // Duke 3d v1.5, Redneck Rampage +}; + +EXTERN int32_t enginecompatibility_mode; /************************************************************************* POSITION VARIABLES: @@ -1520,9 +1527,9 @@ static FORCE_INLINE CONSTEXPR bool inside_p(int32_t const x, int32_t const y, in return; \ } while (0) -static inline int64_t maybe_truncate_to_int32(int64_t val) +static inline int64_t compat_maybe_truncate_to_int32(int64_t val) { - return blooddemohack ? (int32_t)val : val; + return enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? (int32_t)val : val; } static inline int32_t clipmove_old(int32_t *x, int32_t *y, int32_t *z, int16_t *sectnum, int32_t xvect, int32_t yvect, int32_t walldist, diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index 86cd0df0b..fa3ff31b1 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -778,6 +778,9 @@ static FORCE_INLINE void clipmove_tweak_pos(const vec3_t *pos, int32_t gx, int32 { int32_t daz; + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + return; + if (rintersect(pos->x, pos->y, 0, gx, gy, 0, x1, y1, x2, y2, daxptr, dayptr, &daz) == -1) { *daxptr = pos->x; @@ -785,6 +788,34 @@ static FORCE_INLINE void clipmove_tweak_pos(const vec3_t *pos, int32_t gx, int32 } } +int32_t getceilzofslope_old(int32_t sectnum, int32_t dax, int32_t day) +{ + int32_t dx, dy, i, j; + + if (!(sector[sectnum].ceilingstat&2)) return sector[sectnum].ceilingz; + j = sector[sectnum].wallptr; + dx = wall[wall[j].point2].x-wall[j].x; + dy = wall[wall[j].point2].y-wall[j].y; + i = (ksqrtasm_old(dx*dx+dy*dy)); if (i == 0) return(sector[sectnum].ceilingz); + i = divscale20(sector[sectnum].ceilingheinum,i); + dx *= i; dy *= i; + return(sector[sectnum].ceilingz+dmulscale23(dx,day-wall[j].y,-dy,dax-wall[j].x)); +} + +int32_t getflorzofslope_old(int32_t sectnum, int32_t dax, int32_t day) +{ + int32_t dx, dy, i, j; + + if (!(sector[sectnum].floorstat&2)) return sector[sectnum].floorz; + j = sector[sectnum].wallptr; + dx = wall[wall[j].point2].x-wall[j].x; + dy = wall[wall[j].point2].y-wall[j].y; + i = (ksqrtasm_old(dx*dx+dy*dy)); if (i == 0) return sector[sectnum].floorz; + i = divscale20(sector[sectnum].floorheinum,i); + dx *= i; dy *= i; + return(sector[sectnum].floorz+dmulscale23(dx,day-wall[j].y,-dy,dax-wall[j].x)); +} + // Returns: should clip? static int cliptestsector(int const dasect, int const nextsect, int32_t const flordist, int32_t const ceildist, vec2_t const pos, int32_t const posz) { @@ -792,7 +823,25 @@ static int cliptestsector(int const dasect, int const nextsect, int32_t const fl auto const sec2 = (usectorptr_t)§or[nextsect]; - if (blooddemohack) + switch (enginecompatibility_mode) + { + case ENGINECOMPATIBILITY_NONE: + break; + case ENGINECOMPATIBILITY_19950829: + { + int32_t daz = getflorzofslope_old(dasect, pos.x, pos.y); + int32_t daz2 = getflorzofslope_old(nextsect, pos.x, pos.y); + + if (daz2 < daz && (sec2->floorstat&1) == 0) + if (posz >= daz2-(flordist-1)) return 1; + daz = getceilzofslope_old(dasect, pos.x, pos.y); + daz2 = getceilzofslope_old(nextsect, pos.x, pos.y); + if (daz2 > daz && (sec2->ceilingstat&1) == 0) + if (posz <= daz2+(ceildist-1)) return 1; + + return 0; + } + default: { int32_t daz = getflorzofslope(dasect, pos.x, pos.y); int32_t daz2 = getflorzofslope(nextsect, pos.x, pos.y); @@ -806,6 +855,7 @@ static int cliptestsector(int const dasect, int const nextsect, int32_t const fl return 0; } + } int32_t daz2 = sec2->floorz; int32_t dacz2 = sec2->ceilingz; @@ -817,6 +867,7 @@ static int cliptestsector(int const dasect, int const nextsect, int32_t const fl return 1; auto const sec = (usectorptr_t)§or[dasect]; + int32_t daz = sec->floorz; int32_t dacz = sec->ceilingz; @@ -961,7 +1012,7 @@ static int get_floorspr_clipyou(vec2_t const v1, vec2_t const v2, vec2_t const v static void clipupdatesector(vec2_t const pos, int16_t * const sectnum, int const walldist) { - if (blooddemohack) + if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE) { updatesector(pos.x, pos.y, sectnum); return; @@ -1044,7 +1095,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int //Extra walldist for sprites on sector lines vec2_t const diff = { goal.x - (pos->x), goal.y - (pos->y) }; - int32_t const rad = nsqrtasm(maybe_truncate_to_int32(uhypsq(diff.x, diff.y))) + MAXCLIPDIST + walldist + 8; + int32_t const rad = clip_nsqrtasm(compat_maybe_truncate_to_int32(uhypsq(diff.x, diff.y))) + MAXCLIPDIST + walldist + 8; vec2_t const clipMin = { cent.x - rad, cent.y - rad }; vec2_t const clipMax = { cent.x + rad, cent.y + rad }; @@ -1188,7 +1239,8 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int } // We're not interested in any sector reached by portal traversal that we're "inside" of. - if (!blooddemohack && !curspr && dasect != initialsectnum && inside(pos->x, pos->y, dasect) == 1) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE && !curspr && dasect != initialsectnum + && inside(pos->x, pos->y, dasect) == 1) { int k; for (k=startwall; k 0) v.x = -v.x; v.y = walldist; if (d.x < 0) v.y = -v.y; - if (!blooddemohack && d.x * (pos->y-p1.y-v.y) < (pos->x-p1.x-v.x) * d.y) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE && d.x * (pos->y-p1.y-v.y) < (pos->x-p1.x-v.x) * d.y) v.x >>= 1, v.y >>= 1; addclipline(p1.x+v.x, p1.y+v.y, p2.x+v.x, p2.y+v.y, objtype, false); @@ -1371,7 +1423,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int do { - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) for (native_t i=clipnum-1;i>=0;--i) { if (!bitmap_test(clipignore, i) && clipinsideboxline(pos->x, pos->y, clipit[i].x1, clipit[i].y1, clipit[i].x2, clipit[i].y2, walldist)) @@ -1389,25 +1441,36 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int if ((hitwall = cliptrace(pos->vec2, &vec)) >= 0) { vec2_t const clipr = { clipit[hitwall].x2 - clipit[hitwall].x1, clipit[hitwall].y2 - clipit[hitwall].y1 }; - int64_t const templl = maybe_truncate_to_int32((int64_t)clipr.x * clipr.x + (int64_t)clipr.y * clipr.y); + int64_t const templl = compat_maybe_truncate_to_int32((int64_t)clipr.x * clipr.x + (int64_t)clipr.y * clipr.y); if (templl > 0) { - int64_t const templl2 = maybe_truncate_to_int32((int64_t)(goal.x-vec.x)*clipr.x + (int64_t)(goal.y-vec.y)*clipr.y); - int32_t const i = ((llabs(templl2)>>11) < templl) ? divscale64(templl2, templl, 20) : 0; + int64_t const templl2 = compat_maybe_truncate_to_int32((int64_t)(goal.x-vec.x)*clipr.x + (int64_t)(goal.y-vec.y)*clipr.y); + int32_t const i = enginecompatibility_mode == ENGINECOMPATIBILITY_19950829 || ((llabs(templl2)>>11) < templl) ? + divscale64(templl2, templl, 20) : 0; goal = { mulscale20(clipr.x, i)+vec.x, mulscale20(clipr.y, i)+vec.y }; } - int32_t const tempint = dmulscale6(clipr.x, move.x, clipr.y, move.y); + int32_t tempint; + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + tempint = clipr.x*(move.x>>6)+clipr.y*(move.y>>6); + else + tempint = dmulscale6(clipr.x, move.x, clipr.y, move.y); for (native_t i=cnt+1, j; i<=clipmoveboxtracenum; ++i) { j = hitwalls[i]; - if ((tempint ^ dmulscale6(clipit[j].x2-clipit[j].x1, move.x, clipit[j].y2-clipit[j].y1, move.y)) < 0) + int32_t tempint2; + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + tempint2 = (clipit[j].x2-clipit[j].x1)*(move.x>>6)+(clipit[j].y2-clipit[j].y1)*(move.y>>6); + else + tempint2 = dmulscale6(clipit[j].x2-clipit[j].x1, move.x, clipit[j].y2-clipit[j].y1, move.y); + + if ((tempint ^ tempint2) < 0) { - if (blooddemohack == 1) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19961112) updatesector(pos->x, pos->y, sectnum); return clipReturn; } @@ -1422,7 +1485,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int hitwalls[cnt] = hitwall; } - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) clipupdatesector(vec, sectnum, rad); pos->x = vec.x; @@ -1430,7 +1493,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int cnt--; } while ((xvect|yvect) != 0 && hitwall >= 0 && cnt > 0); - if (blooddemohack) + if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE) { for (native_t j=0; jx, pos->y, clipsectorlist[j]) == 1) @@ -1444,7 +1507,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int for (native_t j=numsectors-1; j>=0; j--) if (inside(pos->x, pos->y, j) == 1) { - if (sector[j].ceilingstat&2) + if (enginecompatibility_mode != ENGINECOMPATIBILITY_19950829 && (sector[j].ceilingstat&2)) tempint2 = getceilzofslope(j, pos->x, pos->y) - pos->z; else tempint2 = sector[j].ceilingz - pos->z; @@ -1458,7 +1521,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int } else { - if (sector[j].floorstat&2) + if (enginecompatibility_mode != ENGINECOMPATIBILITY_19950829 && (sector[j].floorstat&2)) tempint2 = pos->z - getflorzofslope(j, pos->x, pos->y); else tempint2 = pos->z - sector[j].floorz; @@ -1565,23 +1628,29 @@ int pushmove(vec3_t *const vect, int16_t *const sectnum, else { int32_t daz2; + vec2_t closest; - //Find closest point on wall (dax, day) to (vect->x, vect->y) - int32_t dax = wall[wal->point2].x-wal->x; - int32_t day = wall[wal->point2].y-wal->y; - int32_t daz = dax*((vect->x)-wal->x) + day*((vect->y)-wal->y); - int32_t t; - if (daz <= 0) - t = 0; + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + closest = vect->vec2; else { - daz2 = dax*dax+day*day; - if (daz >= daz2) t = (1<<30); else t = divscale30(daz, daz2); - } - dax = wal->x + mulscale30(dax, t); - day = wal->y + mulscale30(day, t); + //Find closest point on wall (dax, day) to (vect->x, vect->y) + int32_t dax = wall[wal->point2].x-wal->x; + int32_t day = wall[wal->point2].y-wal->y; + int32_t daz = dax*((vect->x)-wal->x) + day*((vect->y)-wal->y); + int32_t t; + if (daz <= 0) + t = 0; + else + { + daz2 = dax*dax+day*day; + if (daz >= daz2) t = (1<<30); else t = divscale30(daz, daz2); + } + dax = wal->x + mulscale30(dax, t); + day = wal->y + mulscale30(day, t); - vec2_t closest = { dax, day }; + closest = { dax, day }; + } j = cliptestsector(clipsectorlist[clipsectcnt], wal->nextsector, flordist, ceildist, closest, vect->z); } @@ -1647,9 +1716,15 @@ void getzrange(const vec3_t *pos, int16_t sectnum, const int32_t dasprclipmask = (cliptype>>16); vec2_t closest = { pos->x, pos->y }; - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) getsectordist(closest, sectnum, &closest); - getzsofslope(sectnum,closest.x,closest.y,ceilz,florz); + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + { + *ceilz = getceilzofslope_old(sectnum,closest.x,closest.y); + *florz = getflorzofslope_old(sectnum,closest.x,closest.y); + } + else + getzsofslope(sectnum,closest.x,closest.y,ceilz,florz); *ceilhit = sectnum+16384; *florhit = sectnum+16384; #ifdef YAX_ENABLE @@ -1703,13 +1778,13 @@ restart_grand: int32_t daz, daz2; closest = { pos->x, pos->y }; - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) getsectordist(closest, k, &closest); getzsofslope(k,closest.x,closest.y,&daz,&daz2); int32_t fz, cz; closest = { pos->x, pos->y }; - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) getsectordist(closest, sectq[clipinfo[curidx].qend], &closest); getzsofslope(sectq[clipinfo[curidx].qend],closest.x,closest.y,&cz,&fz); @@ -1795,9 +1870,15 @@ restart_grand: //It actually got here, through all the continue's!!! int32_t daz, daz2; closest = { pos->x, pos->y }; - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) getsectordist(closest, k, &closest); - getzsofslope(k, closest.x,closest.y, &daz,&daz2); + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + { + daz = getceilzofslope_old(k, closest.x,closest.y); + daz2 = getflorzofslope_old(k, closest.x,closest.y); + } + else + getzsofslope(k, closest.x,closest.y, &daz,&daz2); #ifdef HAVE_CLIPSHAPE_FEATURE if (curspr) @@ -1805,7 +1886,7 @@ restart_grand: int32_t fz,cz, hitwhat=(curspr-(uspritetype *)sprite)+49152; closest = { pos->x, pos->y }; - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) getsectordist(closest, sectq[clipinfo[curidx].qend], &closest); getzsofslope(sectq[clipinfo[curidx].qend],closest.x,closest.y,&cz,&fz); @@ -1992,7 +2073,7 @@ restart_grand: addclipsect(j); closest = { pos->x, pos->y }; - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) getsectordist(closest, j, &closest); int const daz = getceilzofslope(j, closest.x, closest.y); @@ -2033,7 +2114,7 @@ restart_grand: addclipsect(j); closest = { pos->x, pos->y }; - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) getsectordist(closest, j, &closest); int const daz = getflorzofslope(j, closest.x,closest.y); @@ -2125,7 +2206,7 @@ static int32_t hitscan_trysector(const vec3_t *sv, usectorptr_t sec, hitdata_t * auto const wal2 = (uwallptr_t)&wall[wal->point2]; int32_t j, dax=wal2->x-wal->x, day=wal2->y-wal->y; - i = nsqrtasm(maybe_truncate_to_int32(uhypsq(dax,day))); if (i == 0) return 1; //continue; + i = nsqrtasm(compat_maybe_truncate_to_int32(uhypsq(dax,day))); if (i == 0) return 1; //continue; i = divscale15(heinum,i); dax *= i; day *= i; @@ -2272,10 +2353,13 @@ restart_grand: else tmp[2] = 0; } #endif - if (hitscan_trysector(sv, sec, hit, vx,vy,vz, sec->ceilingstat, sec->ceilingheinum, sec->ceilingz, -i, tmpptr)) - continue; - if (hitscan_trysector(sv, sec, hit, vx,vy,vz, sec->floorstat, sec->floorheinum, sec->floorz, i, tmpptr)) - continue; + if (enginecompatibility_mode != ENGINECOMPATIBILITY_19950829) + { + if (hitscan_trysector(sv, sec, hit, vx,vy,vz, sec->ceilingstat, sec->ceilingheinum, sec->ceilingz, -i, tmpptr)) + continue; + if (hitscan_trysector(sv, sec, hit, vx,vy,vz, sec->floorstat, sec->floorheinum, sec->floorz, i, tmpptr)) + continue; + } ////////// Walls ////////// @@ -2291,26 +2375,63 @@ restart_grand: x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y; - if (maybe_truncate_to_int32((coord_t)(x1-sv->x)*(y2-sv->y)) < maybe_truncate_to_int32((coord_t)(x2-sv->x)*(y1-sv->y))) continue; + if (compat_maybe_truncate_to_int32((coord_t)(x1-sv->x)*(y2-sv->y)) + < compat_maybe_truncate_to_int32((coord_t)(x2-sv->x)*(y1-sv->y))) continue; if (rintersect(sv->x,sv->y,sv->z, vx,vy,vz, x1,y1, x2,y2, &intx,&inty,&intz) == -1) continue; - if (klabs(intx-sv->x)+klabs(inty-sv->y) >= klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y)) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + { + if (vz != 0) + if ((intz <= sec->ceilingz) || (intz >= sec->floorz)) + if (klabs(intx-sv->x)+klabs(inty-sv->y) < klabs(hit->pos.x-sv->x)+klabs(hit->pos.y-sv->y)) + { + //x1,y1,z1 are temp variables + if (vz > 0) z1 = sec->floorz; else z1 = sec->ceilingz; + x1 = sv->x + scale(z1-sv->z,vx,vz); + y1 = sv->y + scale(z1-sv->z,vy,vz); + if (inside(x1,y1,dasector) == 1) + { + hit_set(hit, dasector, -1, -1, x1, y1, z1); + continue; + } + } + } + else if (klabs(intx-sv->x)+klabs(inty-sv->y) >= klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y)) continue; if (!curspr) { - if ((nextsector < 0) || (wal->cstat&dawalclipmask)) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) { - hit_set(hit, dasector, z, -1, intx, inty, intz); - continue; - } + if ((nextsector < 0) || (wal->cstat&dawalclipmask)) + { + if ((klabs(intx-sv->x)+klabs(inty-sv->y) < klabs(hit->pos.x-sv->x)+klabs(hit->pos.y-sv->y))) + hit_set(hit, dasector, z, -1, intx, inty, intz); + continue; + } - int32_t daz2; - getzsofslope(nextsector,intx,inty,&daz,&daz2); - if (intz <= daz || intz >= daz2) + if (intz <= sector[nextsector].ceilingz || intz >= sector[nextsector].floorz) + { + if ((klabs(intx-sv->x)+klabs(inty-sv->y) < klabs(hit->pos.x-sv->x)+klabs(hit->pos.y-sv->y))) + hit_set(hit, dasector, z, -1, intx, inty, intz); + continue; + } + } + else { - hit_set(hit, dasector, z, -1, intx, inty, intz); - continue; + if ((nextsector < 0) || (wal->cstat&dawalclipmask)) + { + hit_set(hit, dasector, z, -1, intx, inty, intz); + continue; + } + + int32_t daz2; + getzsofslope(nextsector,intx,inty,&daz,&daz2); + if (intz <= daz || intz >= daz2) + { + hit_set(hit, dasector, z, -1, intx, inty, intz); + continue; + } } } #ifdef HAVE_CLIPSHAPE_FEATURE @@ -2393,7 +2514,8 @@ restart_grand: get_wallspr_points(spr, &x1, &x2, &y1, &y2); if ((cstat&64) != 0) //back side of 1-way sprite - if (maybe_truncate_to_int32((coord_t)(x1-sv->x)*(y2-sv->y)) < maybe_truncate_to_int32((coord_t)(x2-sv->x)*(y1-sv->y))) continue; + if (compat_maybe_truncate_to_int32((coord_t)(x1-sv->x)*(y2-sv->y)) + < compat_maybe_truncate_to_int32((coord_t)(x2-sv->x)*(y1-sv->y))) continue; ucoefup16 = rintersect(sv->x,sv->y,sv->z,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz); if (ucoefup16 == -1) continue; @@ -2438,7 +2560,7 @@ restart_grand: if ((cstat&64) != 0) if ((sv->z > intz) == ((cstat&8)==0)) continue; - if (!blooddemohack) + if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) { // Abyss crash prevention code ((intz-sv->z)*zx overflowing a 8-bit word) // PK: the reason for the crash is not the overflowing (even if it IS a problem; diff --git a/source/build/src/common.cpp b/source/build/src/common.cpp index a46732f1c..c8332fdba 100644 --- a/source/build/src/common.cpp +++ b/source/build/src/common.cpp @@ -223,7 +223,8 @@ int32_t ldist(const void *s1, const void *s2) { auto sp1 = (vec2_t const *)s1; auto sp2 = (vec2_t const *)s2; - return sepldist(sp1->x - sp2->x, sp1->y - sp2->y) + (blooddemohack ? 1 : 0); + return sepldist(sp1->x - sp2->x, sp1->y - sp2->y) + + (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 1 : 0); } int32_t dist(const void *s1, const void *s2) diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index f3ac84a58..a0ac76426 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -176,7 +176,7 @@ static int16_t radarang[1280]; static int32_t qradarang[10240], *radarang2; const char ATTRIBUTE((used)) pow2char_[8] = {1,2,4,8,16,32,64,128}; -uint16_t ATTRIBUTE((used)) sqrtable[4096], ATTRIBUTE((used)) shlookup[4096+256]; +uint16_t ATTRIBUTE((used)) sqrtable[4096], ATTRIBUTE((used)) shlookup[4096+256], ATTRIBUTE((used)) sqrtable_old[2048]; char britable[16][256]; // JBF 20040207: full 8bit precision @@ -198,7 +198,6 @@ static fix16_t global100horiz; // (-100..300)-scale horiz (the one passed to dr int32_t(*getpalookup_replace)(int32_t davis, int32_t dashade) = NULL; int32_t bloodhack = 0; -int32_t blooddemohack = 0; // adapted from build.c static void getclosestpointonwall_internal(vec2_t const p, int32_t const dawall, vec2_t *const closest) @@ -7475,6 +7474,8 @@ static uint32_t msqrtasm(uint32_t c) static inline void initksqrt(void) { int32_t i, j, k; + uint32_t root, num; + int32_t temp; j = 1; k = 0; for (i=0; i<4096; i++) @@ -7484,6 +7485,29 @@ static inline void initksqrt(void) shlookup[i] = (k<<1)+((10-k)<<8); if (i < 256) shlookup[i+4096] = ((k+6)<<1)+((10-(k+6))<<8); } + + for(i=0;i<2048;i++) + { + root = 128; + num = i<<20; + do + { + temp = root; + root = (root+num/root)>>1; + } while((temp-root+1) > 2); + temp = root*root-num; + while (klabs(int32_t(temp-2*root+1)) < klabs(temp)) + { + temp += -(2*root)+1; + root--; + } + while (klabs(int32_t(temp+2*root+1)) < klabs(temp)) + { + temp += 2*root+1; + root++; + } + sqrtable_old[i] = root; + } } @@ -7736,7 +7760,7 @@ LISTFN_STATIC int32_t insertspritestat(int16_t statnum) // make back-link of the new freelist head point to nil if (headspritestat[MAXSTATUS] >= 0) prevspritestat[headspritestat[MAXSTATUS]] = -1; - else if (!blooddemohack) + else if (enginecompatibility_mode == ENGINECOMPATIBILITY_NONE) tailspritefree = -1; do_insertsprite_at_headofstat(blanktouse, statnum); @@ -7805,7 +7829,7 @@ int32_t deletesprite(int16_t spritenum) sprite[spritenum].sectnum = MAXSECTORS; // insert at tail of status freelist - if (blooddemohack) + if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE) do_insertsprite_at_headofstat(spritenum, MAXSTATUS); else { @@ -7886,7 +7910,7 @@ int32_t lintersect(const int32_t originX, const int32_t originY, const int32_t o if (rayCrossLineVec == 0) { - if (originDiffCrossRay != 0 || blooddemohack) + if (originDiffCrossRay != 0 || enginecompatibility_mode != ENGINECOMPATIBILITY_NONE) { // line segments are parallel return 0; @@ -8000,7 +8024,7 @@ int32_t rintersect(int32_t x1, int32_t y1, int32_t z1, { //p1 towards p2 is a ray - if (blooddemohack) + if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE) return rintersect_old(x1,y1,z1,vx,vy,vz,x3,y3,x4,y4,intx,inty,intz); int64_t const x34=x3-x4, y34=y3-y4; @@ -10710,7 +10734,32 @@ void vox_undefine(int32_t const tile) // // See http://fabiensanglard.net/duke3d/build_engine_internals.php, // "Inside details" for the idea behind the algorithm. +int32_t inside_ps(int32_t x, int32_t y, int16_t sectnum) +{ + if (sectnum >= 0 && sectnum < numsectors) + { + int32_t cnt = 0; + auto wal = (uwallptr_t)&wall[sector[sectnum].wallptr]; + int wallsleft = sector[sectnum].wallnum; + do + { + vec2_t v1 = { wal->x - x, wal->y - y }; + auto const &wal2 = *(uwallptr_t)&wall[wal->point2]; + vec2_t v2 = { wal2.x - x, wal2.y - y }; + + if ((v1.y^v2.y) < 0) + cnt ^= (((v1.x^v2.x) < 0) ? (v1.x*v2.y= 0)); + + wal++; + } + while (--wallsleft); + + return cnt; + } + + return -1; +} int32_t inside_old(int32_t x, int32_t y, int16_t sectnum) { if (sectnum >= 0 && sectnum < numsectors) @@ -10748,8 +10797,15 @@ int32_t inside_old(int32_t x, int32_t y, int16_t sectnum) int32_t inside(int32_t x, int32_t y, int16_t sectnum) { - if (blooddemohack) + switch (enginecompatibility_mode) + { + case ENGINECOMPATIBILITY_NONE: + break; + case ENGINECOMPATIBILITY_19950829: + return inside_ps(x, y, sectnum); + default: return inside_old(x, y, sectnum); + } if ((unsigned)sectnum < (unsigned)numsectors) { uint32_t cnt1 = 0, cnt2 = 0; @@ -10946,8 +11002,48 @@ int32_t nextsectorneighborz(int16_t sectnum, int32_t refz, int16_t topbottom, in // // cansee // +int32_t cansee_old(int32_t xs, int32_t ys, int32_t zs, int16_t sectnums, int32_t xe, int32_t ye, int32_t ze, int16_t sectnume) +{ + sectortype *sec, *nsec; + walltype *wal, *wal2; + int32_t intx, inty, intz, i, cnt, nextsector, dasectnum, dacnt, danum; + + if ((xs == xe) && (ys == ye) && (sectnums == sectnume)) return 1; + + clipsectorlist[0] = sectnums; danum = 1; + for(dacnt=0;dacntwallnum,wal=&wall[sec->wallptr];cnt>0;cnt--,wal++) + { + wal2 = &wall[wal->point2]; + if (lintersect(xs,ys,zs,xe,ye,ze,wal->x,wal->y,wal2->x,wal2->y,&intx,&inty,&intz) != 0) + { + nextsector = wal->nextsector; if (nextsector < 0) return 0; + + if (intz <= sec->ceilingz) return 0; + if (intz >= sec->floorz) return 0; + nsec = §or[nextsector]; + if (intz <= nsec->ceilingz) return 0; + if (intz >= nsec->floorz) return 0; + + for(i=danum-1;i>=0;i--) + if (clipsectorlist[i] == nextsector) break; + if (i < 0) clipsectorlist[danum++] = nextsector; + } + } + + if (clipsectorlist[dacnt] == sectnume) + return 1; + } + return 0; +} + int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1, int32_t x2, int32_t y2, int32_t z2, int16_t sect2) { + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + return cansee_old(x1, y1, z2, sect1, x2, y2, z2, sect2); int32_t dacnt, danum; const int32_t x21 = x2-x1, y21 = y2-y1, z21 = z2-z1; @@ -11559,7 +11655,7 @@ int findwallbetweensectors(int sect1, int sect2) // void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum) { - if (blooddemohack) + if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE) { if (inside_p(x, y, *sectnum)) return; @@ -11629,7 +11725,7 @@ void updatesectorexclude(int32_t const x, int32_t const y, int16_t * const sectn void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum) { - if (blooddemohack) + if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE) { if ((uint32_t)(*sectnum) < 2*MAXSECTORS) { @@ -12416,7 +12512,7 @@ int32_t getceilzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day) if (i == 0) return sec->ceilingz; int const j = dmulscale3(d.x, day-w.y, -d.y, dax-w.x); - int const shift = blooddemohack ? 0 : 1; + int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1; return sec->ceilingz + (scale(sec->ceilingheinum,j>>shift,i)<floorz; int const j = dmulscale3(d.x, day-w.y, -d.y, dax-w.x); - int const shift = blooddemohack ? 0 : 1; + int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1; return sec->floorz + (scale(sec->floorheinum,j>>shift,i)<y, -d.y,dax-wal->x); - int const shift = blooddemohack ? 0 : 1; + int const shift = enginecompatibility_mode != ENGINECOMPATIBILITY_NONE ? 0 : 1; if (sec->ceilingstat&2) *ceilz += scale(sec->ceilingheinum,j>>shift,i)<floorstat&2) diff --git a/source/build/src/engine_priv.h b/source/build/src/engine_priv.h index f7a3f39a1..11472a5a4 100644 --- a/source/build/src/engine_priv.h +++ b/source/build/src/engine_priv.h @@ -28,7 +28,7 @@ extern int32_t globalx1, globaly2; -extern uint16_t ATTRIBUTE((used)) sqrtable[4096], ATTRIBUTE((used)) shlookup[4096+256]; +extern uint16_t ATTRIBUTE((used)) sqrtable[4096], ATTRIBUTE((used)) shlookup[4096+256], ATTRIBUTE((used)) sqrtable_old[2048]; static inline int32_t nsqrtasm(uint32_t a) @@ -71,6 +71,23 @@ extern uint16_t ATTRIBUTE((used)) sqrtable[4096], ATTRIBUTE((used)) shlookup[409 } +inline int32_t ksqrtasm_old(int32_t n) +{ + n = klabs(n); + int shift; + for (shift = 0; n >= 2048; n >>=2, shift++) + { + } + return (sqrtable_old[n]<>10; +} + +inline int32_t clip_nsqrtasm(int32_t n) +{ + if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829) + return ksqrtasm_old(n); + return nsqrtasm(n); +} + extern int16_t thesector[MAXWALLSB], thewall[MAXWALLSB]; extern int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB]; extern int16_t maskwall[MAXWALLSB], maskwallcnt; diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index 1e532bc14..5496412e2 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -7456,7 +7456,7 @@ static void G_Startup(void) G_CompileScripts(); - blooddemohack = 1; + enginecompatibility_mode = ENGINECOMPATIBILITY_19961112; if (engineInit()) G_FatalEngineError();