Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2214-pre4
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-167
  • fix-cvar-conflicts
  • fix-opengl-parameter-crash
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • just-in-case
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • map-components-signedness-fixes
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.15
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
142 results

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
117 results
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • better-player-states
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-1258
  • fix-1277
  • fix-167
  • fix-cvar-conflicts
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • gitlab-ci
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-debug-library
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • map-components-signedness-fixes
  • master
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
141 results
Show changes
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -100,6 +100,281 @@ void R_DrawColumn_8(void) ...@@ -100,6 +100,281 @@ void R_DrawColumn_8(void)
} }
} }
/** \brief The R_DrawColumnClamped_8 function
Same as R_DrawColumn_8, but prevents artifacts from showing up (caused by fixed-point imprecisions)
*/
void R_DrawColumnClamped_8(void)
{
INT32 count;
UINT8 *dest;
fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
if (count < 0) // Zero length, column does not exceed a pixel.
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
return;
#endif
// Framebuffer destination address.
dest = &topleft[dc_yl*vid.width + dc_x];
count++;
// Determine scaling, which is the only mapping to be done.
fracstep = dc_iscale;
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
// This is as fast as it gets.
{
const UINT8 *source = dc_source;
const lighttable_t *colormap = dc_colormap;
INT32 heightmask = dc_texheight-1;
INT32 idx;
if (dc_texheight & heightmask) // not a power of 2 -- killough
{
heightmask++;
heightmask <<= FRACBITS;
if (frac < 0)
while ((frac += heightmask) < 0);
else
while (frac >= heightmask)
frac -= heightmask;
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix
idx = frac>>FRACBITS;
if (idx >= 0 && idx < dc_postlength)
*dest = colormap[source[idx]];
dest += vid.width;
// Avoid overflow.
if (fracstep > 0x7FFFFFFF - frac)
frac += fracstep - heightmask;
else
frac += fracstep;
while (frac >= heightmask)
frac -= heightmask;
} while (--count);
}
else
{
while ((count -= 2) >= 0) // texture height is a power of 2
{
idx = (frac>>FRACBITS) & heightmask;
if (idx >= 0 && idx < dc_postlength)
*dest = colormap[source[idx]];
dest += vid.width;
frac += fracstep;
idx = (frac>>FRACBITS) & heightmask;
if (idx >= 0 && idx < dc_postlength)
*dest = colormap[source[idx]];
dest += vid.width;
frac += fracstep;
}
if (count & 1)
{
idx = (frac>>FRACBITS) & heightmask;
if (idx >= 0 && idx < dc_postlength)
*dest = colormap[source[idx]];
}
}
}
}
void R_Draw2sMultiPatchColumn_8(void)
{
INT32 count;
register UINT8 *dest;
register fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
if (count < 0) // Zero length, column does not exceed a pixel.
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
return;
#endif
// Framebuffer destination address.
dest = &topleft[dc_yl*vid.width + dc_x];
count++;
// Determine scaling, which is the only mapping to be done.
fracstep = dc_iscale;
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
// This is as fast as it gets.
{
register const UINT8 *source = dc_source;
register const lighttable_t *colormap = dc_colormap;
register INT32 heightmask = dc_texheight-1;
register UINT8 val;
if (dc_texheight & heightmask) // not a power of 2 -- killough
{
heightmask++;
heightmask <<= FRACBITS;
if (frac < 0)
while ((frac += heightmask) < 0);
else
while (frac >= heightmask)
frac -= heightmask;
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix
val = source[frac>>FRACBITS];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
dest += vid.width;
// Avoid overflow.
if (fracstep > 0x7FFFFFFF - frac)
frac += fracstep - heightmask;
else
frac += fracstep;
while (frac >= heightmask)
frac -= heightmask;
} while (--count);
}
else
{
while ((count -= 2) >= 0) // texture height is a power of 2
{
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
dest += vid.width;
frac += fracstep;
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
dest += vid.width;
frac += fracstep;
}
if (count & 1)
{
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = colormap[val];
}
}
}
}
void R_Draw2sMultiPatchTranslucentColumn_8(void)
{
INT32 count;
register UINT8 *dest;
register fixed_t frac;
fixed_t fracstep;
count = dc_yh - dc_yl;
if (count < 0) // Zero length, column does not exceed a pixel.
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
return;
#endif
// Framebuffer destination address.
dest = &topleft[dc_yl*vid.width + dc_x];
count++;
// Determine scaling, which is the only mapping to be done.
fracstep = dc_iscale;
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
// This is as fast as it gets.
{
register const UINT8 *source = dc_source;
register const UINT8 *transmap = dc_transmap;
register const lighttable_t *colormap = dc_colormap;
register INT32 heightmask = dc_texheight-1;
register UINT8 val;
if (dc_texheight & heightmask) // not a power of 2 -- killough
{
heightmask++;
heightmask <<= FRACBITS;
if (frac < 0)
while ((frac += heightmask) < 0);
else
while (frac >= heightmask)
frac -= heightmask;
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix
val = source[frac>>FRACBITS];
if (val != TRANSPARENTPIXEL)
*dest = *(transmap + (colormap[val]<<8) + (*dest));
dest += vid.width;
// Avoid overflow.
if (fracstep > 0x7FFFFFFF - frac)
frac += fracstep - heightmask;
else
frac += fracstep;
while (frac >= heightmask)
frac -= heightmask;
} while (--count);
}
else
{
while ((count -= 2) >= 0) // texture height is a power of 2
{
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = *(transmap + (colormap[val]<<8) + (*dest));
dest += vid.width;
frac += fracstep;
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = *(transmap + (colormap[val]<<8) + (*dest));
dest += vid.width;
frac += fracstep;
}
if (count & 1)
{
val = source[(frac>>FRACBITS) & heightmask];
if (val != TRANSPARENTPIXEL)
*dest = *(transmap + (colormap[val]<<8) + (*dest));
}
}
}
}
/** \brief The R_DrawShadeColumn_8 function /** \brief The R_DrawShadeColumn_8 function
Experiment to make software go faster. Taken from the Boom source Experiment to make software go faster. Taken from the Boom source
*/ */
...@@ -212,6 +487,90 @@ void R_DrawTranslucentColumn_8(void) ...@@ -212,6 +487,90 @@ void R_DrawTranslucentColumn_8(void)
} }
} }
/** \brief The R_DrawTranslucentColumnClamped_8 function
Same as R_DrawTranslucentColumn_8, but prevents artifacts from showing up (caused by fixed-point imprecisions)
*/
void R_DrawTranslucentColumnClamped_8(void)
{
INT32 count;
UINT8 *dest;
fixed_t frac, fracstep;
count = dc_yh - dc_yl + 1;
if (count <= 0) // Zero length, column does not exceed a pixel.
return;
#ifdef RANGECHECK
if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
I_Error("R_DrawTranslucentColumnClamped_8: %d to %d at %d", dc_yl, dc_yh, dc_x);
#endif
dest = &topleft[dc_yl*vid.width + dc_x];
// Looks familiar.
fracstep = dc_iscale;
frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep);
// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
// This is as fast as it gets.
{
const UINT8 *source = dc_source;
const UINT8 *transmap = dc_transmap;
const lighttable_t *colormap = dc_colormap;
INT32 heightmask = dc_texheight - 1;
INT32 idx;
if (dc_texheight & heightmask)
{
heightmask++;
heightmask <<= FRACBITS;
if (frac < 0)
while ((frac += heightmask) < 0)
;
else
while (frac >= heightmask)
frac -= heightmask;
do
{
// Re-map color indices from wall texture column
// using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix
idx = frac>>FRACBITS;
if (idx >= 0 && idx < dc_postlength)
*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
dest += vid.width;
if ((frac += fracstep) >= heightmask)
frac -= heightmask;
}
while (--count);
}
else
{
while ((count -= 2) >= 0) // texture height is a power of 2
{
idx = (frac>>FRACBITS)&heightmask;
if (idx >= 0 && idx < dc_postlength)
*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
dest += vid.width;
frac += fracstep;
idx = (frac>>FRACBITS)&heightmask;
if (idx >= 0 && idx < dc_postlength)
*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
dest += vid.width;
frac += fracstep;
}
if (count & 1)
{
idx = (frac>>FRACBITS)&heightmask;
if (idx >= 0 && idx < dc_postlength)
*dest = *(transmap + (colormap[source[idx]]<<8) + (*dest));
}
}
}
}
// Hack: A cut-down copy of R_DrawTranslucentColumn_8 that does not read texture // Hack: A cut-down copy of R_DrawTranslucentColumn_8 that does not read texture
// data since something about calculating the texture reading address for drop shadows is broken. // data since something about calculating the texture reading address for drop shadows is broken.
// dc_texturemid and dc_iscale get wrong values for drop shadows, however those are not strictly // dc_texturemid and dc_iscale get wrong values for drop shadows, however those are not strictly
...@@ -942,6 +1301,136 @@ void R_DrawTiltedSplat_8(void) ...@@ -942,6 +1301,136 @@ void R_DrawTiltedSplat_8(void)
#endif #endif
} }
void R_DrawTiltedTranslucentSplat_8(void)
{
// x1, x2 = ds_x1, ds_x2
int width = ds_x2 - ds_x1;
double iz, uz, vz;
UINT32 u, v;
int i;
UINT8 *source;
UINT8 *colormap;
UINT8 *dest;
UINT8 val;
double startz, startu, startv;
double izstep, uzstep, vzstep;
double endz, endu, endv;
UINT32 stepu, stepv;
iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx);
uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
R_CalcSlopeLight();
dest = &topleft[ds_y*vid.width + ds_x1];
source = ds_source;
//colormap = ds_colormap;
#if 0 // The "perfect" reference version of this routine. Pretty slow.
// Use it only to see how things are supposed to look.
i = 0;
do
{
double z = 1.f/iz;
u = (INT64)(uz*z);
v = (INT64)(vz*z);
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
dest++;
iz += ds_sz.x;
uz += ds_su.x;
vz += ds_sv.x;
} while (--width >= 0);
#else
startz = 1.f/iz;
startu = uz*startz;
startv = vz*startz;
izstep = ds_sz.x * SPANSIZE;
uzstep = ds_su.x * SPANSIZE;
vzstep = ds_sv.x * SPANSIZE;
//x1 = 0;
width++;
while (width >= SPANSIZE)
{
iz += izstep;
uz += uzstep;
vz += vzstep;
endz = 1.f/iz;
endu = uz*endz;
endv = vz*endz;
stepu = (INT64)((endu - startu) * INVSPAN);
stepv = (INT64)((endv - startv) * INVSPAN);
u = (INT64)(startu);
v = (INT64)(startv);
for (i = SPANSIZE-1; i >= 0; i--)
{
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
dest++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = (INT64)(startu);
v = (INT64)(startv);
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
}
else
{
double left = width;
iz += ds_sz.x * left;
uz += ds_su.x * left;
vz += ds_sv.x * left;
endz = 1.f/iz;
endu = uz*endz;
endv = vz*endz;
left = 1.f/left;
stepu = (INT64)((endu - startu) * left);
stepv = (INT64)((endv - startv) * left);
u = (INT64)(startu);
v = (INT64)(startv);
for (; width != 0; width--)
{
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
dest++;
u += stepu;
v += stepv;
}
}
}
#endif
}
/** \brief The R_DrawSplat_8 function /** \brief The R_DrawSplat_8 function
Just like R_DrawSpan_8, but skips transparent pixels. Just like R_DrawSpan_8, but skips transparent pixels.
*/ */
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -666,6 +666,204 @@ void R_DrawTiltedSplat_NPO2_8(void) ...@@ -666,6 +666,204 @@ void R_DrawTiltedSplat_NPO2_8(void)
#endif #endif
} }
void R_DrawTiltedTranslucentSplat_NPO2_8(void)
{
// x1, x2 = ds_x1, ds_x2
int width = ds_x2 - ds_x1;
double iz, uz, vz;
UINT32 u, v;
int i;
UINT8 *source;
UINT8 *colormap;
UINT8 *dest;
UINT8 val;
double startz, startu, startv;
double izstep, uzstep, vzstep;
double endz, endu, endv;
UINT32 stepu, stepv;
struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth);
struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight);
iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx);
uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
R_CalcSlopeLight();
dest = &topleft[ds_y*vid.width + ds_x1];
source = ds_source;
//colormap = ds_colormap;
#if 0 // The "perfect" reference version of this routine. Pretty slow.
// Use it only to see how things are supposed to look.
i = 0;
do
{
double z = 1.f/iz;
u = (INT64)(uz*z);
v = (INT64)(vz*z);
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
// Lactozilla: Non-powers-of-two
{
fixed_t x = (((fixed_t)u) >> FRACBITS);
fixed_t y = (((fixed_t)v) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
else
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
if (y < 0)
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
else
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
}
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
dest++;
iz += ds_sz.x;
uz += ds_su.x;
vz += ds_sv.x;
} while (--width >= 0);
#else
startz = 1.f/iz;
startu = uz*startz;
startv = vz*startz;
izstep = ds_sz.x * SPANSIZE;
uzstep = ds_su.x * SPANSIZE;
vzstep = ds_sv.x * SPANSIZE;
//x1 = 0;
width++;
while (width >= SPANSIZE)
{
iz += izstep;
uz += uzstep;
vz += vzstep;
endz = 1.f/iz;
endu = uz*endz;
endv = vz*endz;
stepu = (INT64)((endu - startu) * INVSPAN);
stepv = (INT64)((endv - startv) * INVSPAN);
u = (INT64)(startu);
v = (INT64)(startv);
for (i = SPANSIZE-1; i >= 0; i--)
{
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
// Lactozilla: Non-powers-of-two
{
fixed_t x = (((fixed_t)u) >> FRACBITS);
fixed_t y = (((fixed_t)v) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
else
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
if (y < 0)
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
else
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
}
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
dest++;
u += stepu;
v += stepv;
}
startu = endu;
startv = endv;
width -= SPANSIZE;
}
if (width > 0)
{
if (width == 1)
{
u = (INT64)(startu);
v = (INT64)(startv);
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
// Lactozilla: Non-powers-of-two
{
fixed_t x = (((fixed_t)u) >> FRACBITS);
fixed_t y = (((fixed_t)v) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
else
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
if (y < 0)
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
else
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
}
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
}
else
{
double left = width;
iz += ds_sz.x * left;
uz += ds_su.x * left;
vz += ds_sv.x * left;
endz = 1.f/iz;
endu = uz*endz;
endv = vz*endz;
left = 1.f/left;
stepu = (INT64)((endu - startu) * left);
stepv = (INT64)((endv - startv) * left);
u = (INT64)(startu);
v = (INT64)(startv);
for (; width != 0; width--)
{
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
// Lactozilla: Non-powers-of-two
{
fixed_t x = (((fixed_t)u) >> FRACBITS);
fixed_t y = (((fixed_t)v) >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
else
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
if (y < 0)
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
else
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
}
if (val != TRANSPARENTPIXEL)
*dest = *(ds_transmap + (colormap[val] << 8) + *dest);
dest++;
u += stepu;
v += stepv;
}
}
}
#endif
}
/** \brief The R_DrawSplat_NPO2_8 function /** \brief The R_DrawSplat_NPO2_8 function
Just like R_DrawSpan_NPO2_8, but skips transparent pixels. Just like R_DrawSpan_NPO2_8, but skips transparent pixels.
*/ */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom) // Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom)
// Copyright (C) 1999-2019 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -120,6 +120,19 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe ...@@ -120,6 +120,19 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe
return out; return out;
} }
static double R_LerpDouble(double from, double to, double frac)
{
return from + (frac * (to - from));
}
static dvector3_t *R_LerpDVector3(const dvector3_t *from, const dvector3_t *to, double frac, dvector3_t *out)
{
DVector3_Subtract(to, from, out);
DVector3_Multiply(out, frac, out);
DVector3_Add(from, out, out);
return out;
}
// recalc necessary stuff for mouseaiming // recalc necessary stuff for mouseaiming
// slopes are already calculated for the full possible view (which is 4*viewheight). // slopes are already calculated for the full possible view (which is 4*viewheight).
// 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out) // 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
...@@ -497,6 +510,14 @@ void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope) ...@@ -497,6 +510,14 @@ void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope)
FV2_Copy(&interp->dynslope.bakd, &slope->d); FV2_Copy(&interp->dynslope.bakd, &slope->d);
interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta; interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta;
DVector3_Copy(&interp->dynslope.oldorigin, &slope->dorigin);
DVector3_Copy(&interp->dynslope.bakorigin, &slope->dorigin);
DVector3_Copy(&interp->dynslope.oldnormdir, &slope->dnormdir);
DVector3_Copy(&interp->dynslope.baknormdir, &slope->dnormdir);
interp->dynslope.olddzdelta = interp->dynslope.bakdzdelta = slope->dzdelta;
} }
void R_InitializeLevelInterpolators(void) void R_InitializeLevelInterpolators(void)
...@@ -561,6 +582,21 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp) ...@@ -561,6 +582,21 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp)
FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o); FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o);
FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d); FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d);
interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta; interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta;
DVector3_Copy(&interp->dynslope.oldorigin, &interp->dynslope.bakorigin);
DVector3_Copy(&interp->dynslope.oldnormdir, &interp->dynslope.baknormdir);
interp->dynslope.olddzdelta = interp->dynslope.bakdzdelta;
if (interp->dynslope.slope->moved)
{
P_CalculateSlopeVectors(interp->dynslope.slope);
interp->dynslope.slope->moved = false;
}
DVector3_Copy(&interp->dynslope.bakorigin, &interp->dynslope.slope->dorigin);
DVector3_Copy(&interp->dynslope.baknormdir, &interp->dynslope.slope->dnormdir);
interp->dynslope.bakdzdelta = interp->dynslope.slope->dzdelta;
break; break;
} }
} }
...@@ -646,7 +682,13 @@ void R_ApplyLevelInterpolators(fixed_t frac) ...@@ -646,7 +682,13 @@ void R_ApplyLevelInterpolators(fixed_t frac)
R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o); R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o);
R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d); R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d);
interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac); interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac);
interp->dynslope.slope->moved = true; if (rendermode == render_soft)
{
double dfrac = FixedToDouble(frac);
R_LerpDVector3(&interp->dynslope.oldorigin, &interp->dynslope.bakorigin, dfrac, &interp->dynslope.slope->dorigin);
R_LerpDVector3(&interp->dynslope.oldnormdir, &interp->dynslope.baknormdir, dfrac, &interp->dynslope.slope->dnormdir);
interp->dynslope.slope->dzdelta = R_LerpDouble(interp->dynslope.olddzdelta, interp->dynslope.bakdzdelta, dfrac);
}
break; break;
} }
} }
...@@ -704,6 +746,10 @@ void R_RestoreLevelInterpolators(void) ...@@ -704,6 +746,10 @@ void R_RestoreLevelInterpolators(void)
FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako); FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako);
FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd); FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd);
interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta; interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta;
DVector3_Copy(&interp->dynslope.slope->dorigin, &interp->dynslope.bakorigin);
DVector3_Copy(&interp->dynslope.slope->dnormdir, &interp->dynslope.baknormdir);
interp->dynslope.slope->dzdelta = interp->dynslope.bakdzdelta;
break; break;
} }
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom) // Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom)
// Copyright (C) 1999-2019 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -115,6 +115,9 @@ typedef struct levelinterpolator_s { ...@@ -115,6 +115,9 @@ typedef struct levelinterpolator_s {
vector3_t oldo, bako; vector3_t oldo, bako;
vector2_t oldd, bakd; vector2_t oldd, bakd;
fixed_t oldzdelta, bakzdelta; fixed_t oldzdelta, bakzdelta;
dvector3_t oldorigin, bakorigin;
dvector3_t oldnormdir, baknormdir;
double olddzdelta, bakdzdelta;
} dynslope; } dynslope;
}; };
} levelinterpolator_t; } levelinterpolator_t;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -161,7 +161,7 @@ consvar_t cv_translucency = CVAR_INIT ("translucency", "On", CV_SAVE, CV_OnOff, ...@@ -161,7 +161,7 @@ consvar_t cv_translucency = CVAR_INIT ("translucency", "On", CV_SAVE, CV_OnOff,
consvar_t cv_drawdist = CVAR_INIT ("drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL); consvar_t cv_drawdist = CVAR_INIT ("drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL);
consvar_t cv_drawdist_nights = CVAR_INIT ("drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL); consvar_t cv_drawdist_nights = CVAR_INIT ("drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL);
consvar_t cv_drawdist_precip = CVAR_INIT ("drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL); consvar_t cv_drawdist_precip = CVAR_INIT ("drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL);
consvar_t cv_fov = CVAR_INIT ("fov", "90", CV_SAVE|CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange); consvar_t cv_fov = CVAR_INIT ("fov", "100", CV_SAVE|CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange);
consvar_t cv_fovchange = CVAR_INIT ("fovchange", "Off", CV_SAVE, CV_OnOff, NULL); consvar_t cv_fovchange = CVAR_INIT ("fovchange", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL); consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL);
...@@ -390,22 +390,22 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y) ...@@ -390,22 +390,22 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y)
return R_PointToDist2(viewx, viewy, x, y); return R_PointToDist2(viewx, viewy, x, y);
} }
line_t *R_GetFFloorLine(const seg_t *seg, const ffloor_t *pfloor) line_t *R_GetFFloorLine(const line_t *line, const ffloor_t *pfloor, const sector_t *sector)
{ {
if (pfloor->master->flags & ML_TFERLINE) if (pfloor->master->flags & ML_TFERLINE)
{ {
size_t linenum = seg->linedef - pfloor->target->lines[0]; size_t linenum = min((size_t)(line - sector->lines[0]), pfloor->master->frontsector->linecount);
return pfloor->master->frontsector->lines[0] + linenum; return pfloor->master->frontsector->lines[0] + linenum;
} }
else else
return pfloor->master; return pfloor->master;
} }
side_t *R_GetFFloorSide(const seg_t *seg, const ffloor_t *pfloor) side_t *R_GetFFloorSide(const line_t *line, const ffloor_t *pfloor, const sector_t *sector)
{ {
if (pfloor->master->flags & ML_TFERLINE) if (pfloor->master->flags & ML_TFERLINE)
{ {
line_t *newline = R_GetFFloorLine(seg, pfloor); line_t *newline = R_GetFFloorLine(line, pfloor, sector);
return &sides[newline->sidenum[0]]; return &sides[newline->sidenum[0]];
} }
else else
...@@ -1152,8 +1152,14 @@ void R_SetupFrame(player_t *player) ...@@ -1152,8 +1152,14 @@ void R_SetupFrame(player_t *player)
if (quake.epicenter) { if (quake.epicenter) {
// Calculate 3D distance from epicenter, using the camera. // Calculate 3D distance from epicenter, using the camera.
fixed_t xydist = R_PointToDist2(thiscam->x, thiscam->y, quake.epicenter->x, quake.epicenter->y); fixed_t xydist, dist;
fixed_t dist = R_PointToDist2(0, thiscam->z, xydist, quake.epicenter->z); if (P_MobjWasRemoved(r_viewmobj)) {
xydist = R_PointToDist2(thiscam->x, thiscam->y, quake.epicenter->x, quake.epicenter->y);
dist = R_PointToDist2(0, thiscam->z, xydist, quake.epicenter->z);
} else {
xydist = R_PointToDist2(r_viewmobj->x, r_viewmobj->y, quake.epicenter->x, quake.epicenter->y);
dist = R_PointToDist2(0, r_viewmobj->z, xydist, quake.epicenter->z);
}
// More effect closer to epicenter, outside of radius = no effect // More effect closer to epicenter, outside of radius = no effect
if (!quake.radius || dist > quake.radius) if (!quake.radius || dist > quake.radius)
...@@ -1428,6 +1434,9 @@ static void R_PortalFrame(portal_t *portal) ...@@ -1428,6 +1434,9 @@ static void R_PortalFrame(portal_t *portal)
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
if (!P_MobjWasRemoved(portal->viewmobj))
r_viewmobj = portal->viewmobj;
portalclipstart = portal->start; portalclipstart = portal->start;
portalclipend = portal->end; portalclipend = portal->end;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -86,8 +86,8 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); ...@@ -86,8 +86,8 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y);
boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph);
line_t *R_GetFFloorLine(const seg_t *seg, const ffloor_t *pfloor); line_t *R_GetFFloorLine(const line_t *line, const ffloor_t *pfloor, const sector_t *sector);
side_t *R_GetFFloorSide(const seg_t *seg, const ffloor_t *pfloor); side_t *R_GetFFloorSide(const line_t *line, const ffloor_t *pfloor, const sector_t *sector);
// Render stats // Render stats
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // Copyright (C) 2020-2023 by Lactozilla.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -31,14 +31,12 @@ patch_t *Patch_Create(INT16 width, INT16 height) ...@@ -31,14 +31,12 @@ patch_t *Patch_Create(INT16 width, INT16 height)
return patch; return patch;
} }
patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source) patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source, size_t insize)
{ {
patch_t *patch = Patch_Create(0, 0); if (!Picture_CheckIfDoomPatch(source, insize))
if (!source) return NULL;
return patch;
patch->width = SHORT(source->width); patch_t *patch = Patch_Create(SHORT(source->width), SHORT(source->height));
patch->height = SHORT(source->height);
patch->leftoffset = SHORT(source->leftoffset); patch->leftoffset = SHORT(source->leftoffset);
patch->topoffset = SHORT(source->topoffset); patch->topoffset = SHORT(source->topoffset);
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // Copyright (C) 2020-2024 by Lactozilla.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
// Patch functions // Patch functions
patch_t *Patch_Create(INT16 width, INT16 height); patch_t *Patch_Create(INT16 width, INT16 height);
patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source); patch_t *Patch_CreateFromDoomPatch(softwarepatch_t *source, size_t insize);
void Patch_CalcDataSizes(softwarepatch_t *source, size_t *total_pixels, size_t *total_posts); void Patch_CalcDataSizes(softwarepatch_t *source, size_t *total_pixels, size_t *total_posts);
void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width, UINT8 *pixels, column_t *columns, post_t *posts, boolean flip); void Patch_MakeColumns(softwarepatch_t *source, size_t num_columns, INT16 width, UINT8 *pixels, column_t *columns, post_t *posts, boolean flip);
void Patch_Free(patch_t *patch); void Patch_Free(patch_t *patch);
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // Copyright (C) 2020-2023 by Lactozilla.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -54,12 +54,26 @@ INT32 R_GetRollAngle(angle_t rollangle) ...@@ -54,12 +54,26 @@ INT32 R_GetRollAngle(angle_t rollangle)
patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip) patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip)
{ {
rotsprite_t *rotsprite = patch->rotated; rotsprite_t *rotsprite = patch->rotated;
if (rotsprite == NULL || angle < 1 || angle >= ROTANGLES) if (angle < 1 || angle >= ROTANGLES)
return NULL; return NULL;
if (rotsprite == NULL)
{
rotsprite = RotatedPatch_Create(ROTANGLES);
patch->rotated = rotsprite;
}
if (flip) if (flip)
angle += rotsprite->angles; angle += rotsprite->angles;
if (rotsprite->patches[angle] == NULL)
{
INT32 xpivot = 0, ypivot = 0;
xpivot = patch->leftoffset;
ypivot = patch->topoffset;
RotatedPatch_DoRotation(rotsprite, patch, angle, xpivot, ypivot, flip);
}
return rotsprite->patches[angle]; return rotsprite->patches[angle];
} }
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. // Copyright (C) 2020-2023 by Lactozilla.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 2005-2009 by Andrey "entryway" Budko. // Copyright (C) 2005-2009 by Andrey "entryway" Budko.
// Copyright (C) 2018-2023 by Jaime "Lactozilla" Passos. // Copyright (C) 2018-2024 by Lactozilla.
// Copyright (C) 2019-2023 by Sonic Team Junior. // Copyright (C) 2019-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -87,7 +87,12 @@ void *Picture_Convert( ...@@ -87,7 +87,12 @@ void *Picture_Convert(
(void)insize; (void)insize;
if (Picture_IsPatchFormat(outformat)) if (Picture_IsPatchFormat(outformat))
return Picture_PatchConvert(informat, picture, outformat, outsize, inwidth, inheight, inleftoffset, intopoffset, flags); {
void *converted = Picture_PatchConvert(informat, insize, picture, outformat, outsize, inwidth, inheight, inleftoffset, intopoffset, flags);
if (converted == NULL)
I_Error("Picture_Convert: conversion to patch did not result in a valid graphic");
return converted;
}
else if (Picture_IsFlatFormat(outformat)) else if (Picture_IsFlatFormat(outformat))
return Picture_FlatConvert(informat, picture, outformat, outsize, inwidth, intopoffset, flags); return Picture_FlatConvert(informat, picture, outformat, outsize, inwidth, intopoffset, flags);
else else
...@@ -235,8 +240,8 @@ static void *WritePatchPixel_i8o8(void *ptr, void *input) ...@@ -235,8 +240,8 @@ static void *WritePatchPixel_i8o8(void *ptr, void *input)
* \return A pointer to the converted picture. * \return A pointer to the converted picture.
*/ */
void *Picture_PatchConvert( void *Picture_PatchConvert(
pictureformat_t informat, void *picture, pictureformat_t outformat, pictureformat_t informat, size_t insize, void *picture,
size_t *outsize, pictureformat_t outformat, size_t *outsize,
INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset, INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset,
pictureflags_t flags) pictureflags_t flags)
{ {
...@@ -245,7 +250,7 @@ void *Picture_PatchConvert( ...@@ -245,7 +250,7 @@ void *Picture_PatchConvert(
{ {
if (outsize != NULL) if (outsize != NULL)
*outsize = sizeof(patch_t); *outsize = sizeof(patch_t);
return Patch_CreateFromDoomPatch(picture); return Patch_CreateFromDoomPatch(picture, insize);
} }
INT32 outbpp = Picture_FormatBPP(outformat); INT32 outbpp = Picture_FormatBPP(outformat);
...@@ -799,47 +804,44 @@ boolean Picture_IsFlatFormat(pictureformat_t format) ...@@ -799,47 +804,44 @@ boolean Picture_IsFlatFormat(pictureformat_t format)
} }
/** Returns true if the lump is a valid Doom patch. /** Returns true if the lump is a valid Doom patch.
* PICFMT_DOOMPATCH only.
* *
* \param patch Input patch. * \param patch Input patch.
* \param picture Input patch size. * \param picture Input patch size.
* \return True if the input patch is valid. * \return True if the input patch is valid, false if not.
*/ */
boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size) boolean Picture_CheckIfDoomPatch(softwarepatch_t *patch, size_t size)
{ {
INT16 width, height; // Does not meet minimum size requirements
boolean result; if (size < MIN_PATCH_LUMP_SIZE)
return false;
// minimum length of a valid Doom patch INT16 width = SHORT(patch->width);
if (size < 13) INT16 height = SHORT(patch->height);
// Quickly check for the dimensions first.
if (width <= 0 || height <= 0 || width > MAX_PATCH_DIMENSIONS || height > MAX_PATCH_DIMENSIONS)
return false; return false;
width = SHORT(patch->width); // Lump size makes no sense given the width
height = SHORT(patch->height); if (!VALID_PATCH_LUMP_SIZE(size, width))
result = (height > 0 && height <= 16384 && width > 0 && width <= 16384); return false;
if (result)
{
// The dimensions seem like they might be valid for a patch, so // The dimensions seem like they might be valid for a patch, so
// check the column directory for extra security. All columns // check the column directory for extra security. All columns
// must begin after the column directory, and none of them must // must begin after the column directory, and none of them must
// point past the end of the patch. // point past the end of the patch.
INT16 x; for (INT16 x = 0; x < width; x++)
for (x = 0; x < width; x++)
{ {
UINT32 ofs = LONG(patch->columnofs[x]); UINT32 ofs = LONG(patch->columnofs[x]);
// Need one byte for an empty column (but there's patches that don't know that!) // Need one byte for an empty column (but there's patches that don't know that!)
if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size) if (ofs < FIRST_PATCH_LUMP_COLUMN(width) || (size_t)ofs >= size)
{ {
result = false; return false;
break;
}
} }
} }
return result; return true;
} }
/** Converts a texture to a flat. /** Converts a texture to a flat.
...@@ -901,12 +903,13 @@ void *Picture_TextureToFlat(size_t texnum) ...@@ -901,12 +903,13 @@ void *Picture_TextureToFlat(size_t texnum)
*/ */
boolean Picture_IsLumpPNG(const UINT8 *d, size_t s) boolean Picture_IsLumpPNG(const UINT8 *d, size_t s)
{ {
if (s < 67) // https://web.archive.org/web/20230524232139/http://garethrees.org/2007/11/14/pngcrush/ if (s < PNG_MIN_SIZE)
return false; return false;
// Check for PNG file signature using memcmp // Check for PNG file signature using memcmp
// As it may be faster on CPUs with slow unaligned memory access // As it may be faster on CPUs with slow unaligned memory access
// Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature
return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0); return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", PNG_HEADER_SIZE) == 0);
} }
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
...@@ -1373,7 +1376,9 @@ void *Picture_PNGConvert( ...@@ -1373,7 +1376,9 @@ void *Picture_PNGConvert(
} }
// Now, convert it! // Now, convert it!
converted = Picture_PatchConvert(informat, flat, outformat, outsize, (INT32)width, (INT32)height, *leftoffset, *topoffset, flags); converted = Picture_PatchConvert(informat, flatsize, flat, outformat, outsize, (INT32)width, (INT32)height, *leftoffset, *topoffset, flags);
if (converted == NULL)
I_Error("Picture_PNGConvert: conversion to patch did not result in a valid graphic");
Z_Free(flat); Z_Free(flat);
return converted; return converted;
} }
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 2018-2023 by Jaime "Lactozilla" Passos. // Copyright (C) 2018-2024 by Lactozilla.
// Copyright (C) 2019-2023 by Sonic Team Junior. // Copyright (C) 2019-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -55,6 +55,29 @@ enum ...@@ -55,6 +55,29 @@ enum
PICDEPTH_32BPP = 32 PICDEPTH_32BPP = 32
}; };
// Maximum allowed dimensions for a patch
#define MAX_PATCH_DIMENSIONS 8192
// Minimum amount of bytes required for a valid patch lump header
#define MIN_PATCH_LUMP_HEADER_SIZE ((sizeof(INT16) * 4) + sizeof(INT32))
// Minimum length of a valid Doom patch lump
// This is the size of a 1x1 patch.
#define MIN_PATCH_LUMP_SIZE (MIN_PATCH_LUMP_HEADER_SIZE + 1)
// Gets the offset to the very first column in a patch lump
#define FIRST_PATCH_LUMP_COLUMN(width) ((sizeof(INT16) * 4) + ((width) * sizeof(INT32)))
// Checks if the size of a lump is valid for a patch, given a certain width
#define VALID_PATCH_LUMP_SIZE(lumplen, width) ((lumplen) >= FIRST_PATCH_LUMP_COLUMN(width))
// Minimum size of a PNG file.
// See: https://web.archive.org/web/20230524232139/http://garethrees.org/2007/11/14/pngcrush/
#define PNG_MIN_SIZE 67
// Size of a PNG header
#define PNG_HEADER_SIZE 8
void *Picture_Convert( void *Picture_Convert(
pictureformat_t informat, void *picture, pictureformat_t outformat, pictureformat_t informat, void *picture, pictureformat_t outformat,
size_t insize, size_t *outsize, size_t insize, size_t *outsize,
...@@ -62,8 +85,8 @@ void *Picture_Convert( ...@@ -62,8 +85,8 @@ void *Picture_Convert(
pictureflags_t flags); pictureflags_t flags);
void *Picture_PatchConvert( void *Picture_PatchConvert(
pictureformat_t informat, void *picture, pictureformat_t outformat, pictureformat_t informat, size_t insize, void *picture,
size_t *outsize, pictureformat_t outformat, size_t *outsize,
INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset, INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset,
pictureflags_t flags); pictureflags_t flags);
void *Picture_FlatConvert( void *Picture_FlatConvert(
...@@ -104,9 +127,6 @@ typedef struct ...@@ -104,9 +127,6 @@ typedef struct
boolean available; boolean available;
} spriteinfo_t; } spriteinfo_t;
// PNG support
#define PNG_HEADER_SIZE 8
boolean Picture_IsLumpPNG(const UINT8 *d, size_t s); boolean Picture_IsLumpPNG(const UINT8 *d, size_t s);
#ifndef NO_PNG_LUMPS #ifndef NO_PNG_LUMPS
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -83,7 +83,7 @@ static fixed_t planeheight; ...@@ -83,7 +83,7 @@ static fixed_t planeheight;
fixed_t yslopetab[MAXVIDHEIGHT*16]; fixed_t yslopetab[MAXVIDHEIGHT*16];
fixed_t *yslope; fixed_t *yslope;
static fixed_t xoffs, yoffs; static INT64 xoffs, yoffs;
static dvector3_t slope_origin, slope_u, slope_v; static dvector3_t slope_origin, slope_u, slope_v;
static dvector3_t slope_lightu, slope_lightv; static dvector3_t slope_lightu, slope_lightv;
...@@ -182,8 +182,8 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2) ...@@ -182,8 +182,8 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
R_CalculatePlaneRipple(currentplane->viewangle + currentplane->plangle); R_CalculatePlaneRipple(currentplane->viewangle + currentplane->plangle);
ds_xfrac += planeripple.xfrac; ds_xfrac += FixedMul(planeripple.xfrac, currentplane->xscale);
ds_yfrac += planeripple.yfrac; ds_yfrac += FixedMul(planeripple.yfrac, currentplane->yscale);
ds_bgofs >>= FRACBITS; ds_bgofs >>= FRACBITS;
if ((y + ds_bgofs) >= viewheight) if ((y + ds_bgofs) >= viewheight)
...@@ -376,19 +376,25 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li ...@@ -376,19 +376,25 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li
visplane_t *check; visplane_t *check;
unsigned hash; unsigned hash;
float offset_xd = FixedToFloat(xoff) / FixedToFloat(xscale ? xscale : 1);
float offset_yd = FixedToFloat(yoff) / FixedToFloat(yscale ? yscale : 1);
INT64 offset_x = offset_xd * FRACUNIT;
INT64 offset_y = offset_yd * FRACUNIT;
if (!slope) // Don't mess with this right now if a slope is involved if (!slope) // Don't mess with this right now if a slope is involved
{ {
xoff += FixedMul(viewx, xscale); offset_x += viewx;
yoff -= FixedMul(viewy, yscale); offset_y -= viewy;
if (plangle != 0) if (plangle != 0)
{ {
// Add the view offset, rotated by the plane angle. // Add the view offset, rotated by the plane angle.
float ang = ANG2RAD(plangle); float ang = ANG2RAD(plangle);
float x = FixedToFloat(xoff); float x = offset_x / (float)FRACUNIT;
float y = FixedToFloat(yoff); float y = offset_y / (float)FRACUNIT;
xoff = FloatToFixed(x * cos(ang) + y * sin(ang)); offset_x = (x * cos(ang) + y * sin(ang)) * FRACUNIT;
yoff = FloatToFixed(-x * sin(ang) + y * cos(ang)); offset_y = (-x * sin(ang) + y * cos(ang)) * FRACUNIT;
} }
} }
...@@ -399,16 +405,19 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li ...@@ -399,16 +405,19 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li
float ang = ANG2RAD(polyobj->angle); float ang = ANG2RAD(polyobj->angle);
float x = FixedToFloat(polyobj->centerPt.x); float x = FixedToFloat(polyobj->centerPt.x);
float y = FixedToFloat(polyobj->centerPt.y); float y = FixedToFloat(polyobj->centerPt.y);
xoff -= FloatToFixed(x * cos(ang) + y * sin(ang)); offset_x -= (x * cos(ang) + y * sin(ang)) * FRACUNIT;
yoff -= FloatToFixed(x * sin(ang) - y * cos(ang)); offset_y -= (x * sin(ang) - y * cos(ang)) * FRACUNIT;
} }
else else
{ {
xoff -= polyobj->centerPt.x; offset_x -= polyobj->centerPt.x;
yoff += polyobj->centerPt.y; offset_y += polyobj->centerPt.y;
} }
} }
offset_x = ((INT64)offset_x * xscale) / FRACUNIT;
offset_y = ((INT64)offset_y * yscale) / FRACUNIT;
// This appears to fix the Nimbus Ruins sky bug. // This appears to fix the Nimbus Ruins sky bug.
if (picnum == skyflatnum && pfloor) if (picnum == skyflatnum && pfloor)
{ {
...@@ -423,7 +432,7 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li ...@@ -423,7 +432,7 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li
{ {
if (height == check->height && picnum == check->picnum if (height == check->height && picnum == check->picnum
&& lightlevel == check->lightlevel && lightlevel == check->lightlevel
&& xoff == check->xoffs && yoff == check->yoffs && offset_x == check->xoffs && offset_y == check->yoffs
&& xscale == check->xscale && yscale == check->yscale && xscale == check->xscale && yscale == check->yscale
&& planecolormap == check->extra_colormap && planecolormap == check->extra_colormap
&& check->viewx == viewx && check->viewy == viewy && check->viewz == viewz && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz
...@@ -449,8 +458,8 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li ...@@ -449,8 +458,8 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li
check->lightlevel = lightlevel; check->lightlevel = lightlevel;
check->minx = vid.width; check->minx = vid.width;
check->maxx = -1; check->maxx = -1;
check->xoffs = xoff; check->xoffs = offset_x;
check->yoffs = yoff; check->yoffs = offset_y;
check->xscale = xscale; check->xscale = xscale;
check->yscale = yscale; check->yscale = yscale;
check->extra_colormap = planecolormap; check->extra_colormap = planecolormap;
...@@ -658,13 +667,13 @@ static void R_DrawSkyPlane(visplane_t *pl) ...@@ -658,13 +667,13 @@ static void R_DrawSkyPlane(visplane_t *pl)
} }
// Returns the height of the sloped plane at (x, y) as a double // Returns the height of the sloped plane at (x, y) as a double
static double R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) static double R_GetSlopeZAt(const pslope_t *slope, INT64 x, INT64 y)
{ {
// If you want to reimplement this using just the equation constants, use this instead: // If you want to reimplement this using just the equation constants, use this instead:
// (d + a*x + b*y) * -(1.0 / c) // (d + a*x + b*y) * -(1.0 / c)
double px = FixedToDouble(x) - slope->dorigin.x; double px = (x / (double)FRACUNIT) - slope->dorigin.x;
double py = FixedToDouble(y) - slope->dorigin.y; double py = (y / (double)FRACUNIT) - slope->dorigin.y;
double dist = (px * slope->dnormdir.x) + (py * slope->dnormdir.y); double dist = (px * slope->dnormdir.x) + (py * slope->dnormdir.y);
...@@ -672,10 +681,10 @@ static double R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) ...@@ -672,10 +681,10 @@ static double R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y)
} }
// Sets the texture origin vector of the sloped plane. // Sets the texture origin vector of the sloped plane.
static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, fixed_t angle) static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, INT64 xoff, INT64 yoff, fixed_t angle)
{ {
INT64 vx = (INT64)xpos + (INT64)xoff; INT64 vx = (INT64)xpos + xoff;
INT64 vy = (INT64)ypos - (INT64)yoff; INT64 vy = (INT64)ypos - yoff;
float vxf = vx / (float)FRACUNIT; float vxf = vx / (float)FRACUNIT;
float vyf = vy / (float)FRACUNIT; float vyf = vy / (float)FRACUNIT;
...@@ -702,7 +711,7 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, ...@@ -702,7 +711,7 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos,
slope->moved = false; slope->moved = false;
} }
R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, (INT64)xoff, (INT64)yoff, angle);
height = R_GetSlopeZAt(slope, xpos, ypos); height = R_GetSlopeZAt(slope, xpos, ypos);
zeroheight = height - FixedToDouble(zpos); zeroheight = height - FixedToDouble(zpos);
...@@ -735,7 +744,7 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, ...@@ -735,7 +744,7 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos,
} }
// This function calculates all of the vectors necessary for drawing a sloped and scaled plane. // This function calculates all of the vectors necessary for drawing a sloped and scaled plane.
void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, INT64 xoff, INT64 yoff, angle_t angle, angle_t plangle)
{ {
double height, z_at_xy; double height, z_at_xy;
float ang; float ang;
...@@ -836,9 +845,11 @@ static void CalcSlopePlaneVectors(visplane_t *pl, fixed_t xoff, fixed_t yoff) ...@@ -836,9 +845,11 @@ static void CalcSlopePlaneVectors(visplane_t *pl, fixed_t xoff, fixed_t yoff)
{ {
if (!ds_fog && (pl->xscale != FRACUNIT || pl->yscale != FRACUNIT)) if (!ds_fog && (pl->xscale != FRACUNIT || pl->yscale != FRACUNIT))
{ {
float offset_x = FixedToFloat(xoff) / FixedToFloat(pl->xscale ? pl->xscale : 1);
float offset_y = FixedToFloat(yoff) / FixedToFloat(pl->yscale ? pl->yscale : 1);
R_SetScaledSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, R_SetScaledSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz,
FixedDiv(FRACUNIT, pl->xscale), FixedDiv(FRACUNIT, pl->yscale), FixedDiv(FRACUNIT, pl->xscale), FixedDiv(FRACUNIT, pl->yscale),
FixedDiv(xoff, pl->xscale), FixedDiv(yoff, pl->yscale), pl->viewangle, pl->plangle); (INT64)(offset_x * FRACUNIT), (INT64)(offset_y * FRACUNIT), pl->viewangle, pl->plangle);
} }
else else
R_SetSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, xoff, yoff, pl->viewangle, pl->plangle); R_SetSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, xoff, yoff, pl->viewangle, pl->plangle);
...@@ -910,7 +921,7 @@ void R_DrawSinglePlane(visplane_t *pl) ...@@ -910,7 +921,7 @@ void R_DrawSinglePlane(visplane_t *pl)
if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
light = (pl->lightlevel >> LIGHTSEGSHIFT); light = (pl->lightlevel >> LIGHTSEGSHIFT);
else else // TODO: 2.3: Make transparent polyobject planes always use light level
light = LIGHTLEVELS-1; light = LIGHTLEVELS-1;
} }
else else
...@@ -952,7 +963,7 @@ void R_DrawSinglePlane(visplane_t *pl) ...@@ -952,7 +963,7 @@ void R_DrawSinglePlane(visplane_t *pl)
if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
light = (pl->lightlevel >> LIGHTSEGSHIFT); light = (pl->lightlevel >> LIGHTSEGSHIFT);
else else // TODO: 2.3: Make transparent FOF planes use light level instead of always being fullbright
light = LIGHTLEVELS-1; light = LIGHTLEVELS-1;
} }
else if (pl->ffloor->fofflags & FOF_FOG) else if (pl->ffloor->fofflags & FOF_FOG)
...@@ -1079,6 +1090,9 @@ void R_DrawSinglePlane(visplane_t *pl) ...@@ -1079,6 +1090,9 @@ void R_DrawSinglePlane(visplane_t *pl)
case SPANDRAWFUNC_SPLAT: case SPANDRAWFUNC_SPLAT:
spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; spanfunctype = SPANDRAWFUNC_TILTEDSPLAT;
break; break;
case SPANDRAWFUNC_TRANSSPLAT:
spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPLAT;
break;
case SPANDRAWFUNC_SOLID: case SPANDRAWFUNC_SOLID:
spanfunctype = SPANDRAWFUNC_TILTEDSOLID; spanfunctype = SPANDRAWFUNC_TILTEDSOLID;
break; break;
......
...@@ -48,7 +48,7 @@ typedef struct visplane_s ...@@ -48,7 +48,7 @@ typedef struct visplane_s
UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend; UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend;
INT32 high, low; // R_PlaneBounds should set these. INT32 high, low; // R_PlaneBounds should set these.
fixed_t xoffs, yoffs; // Scrolling flats. INT64 xoffs, yoffs; // Scrolling flats.
fixed_t xscale, yscale; fixed_t xscale, yscale;
sector_t *sector; sector_t *sector;
...@@ -85,7 +85,7 @@ void R_DrawSinglePlane(visplane_t *pl); ...@@ -85,7 +85,7 @@ void R_DrawSinglePlane(visplane_t *pl);
// Calculates the slope vectors needed for tilted span drawing. // Calculates the slope vectors needed for tilted span drawing.
void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle);
void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, INT64 xoff, INT64 yoff, angle_t angle, angle_t plangle);
typedef struct planemgr_s typedef struct planemgr_s
{ {
......
...@@ -101,7 +101,7 @@ void Portal_ClipApply (const portal_t* portal) ...@@ -101,7 +101,7 @@ void Portal_ClipApply (const portal_t* portal)
static portal_t* Portal_Add (const INT16 x1, const INT16 x2) static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
{ {
portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); portal_t *portal = Z_Calloc(sizeof(portal_t), PU_LEVEL, NULL);
INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL);
fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL); fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL);
...@@ -117,7 +117,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) ...@@ -117,7 +117,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
portal_cap->next = portal; portal_cap->next = portal;
portal_cap = portal; portal_cap = portal;
} }
portal->next = NULL; portal->clipline = -1;
// Store clipping values so they can be restored once the portal is rendered. // Store clipping values so they can be restored once the portal is rendered.
portal->ceilingclip = ceilingclipsave; portal->ceilingclip = ceilingclipsave;
...@@ -142,11 +142,9 @@ void Portal_Remove (portal_t* portal) ...@@ -142,11 +142,9 @@ void Portal_Remove (portal_t* portal)
Z_Free(portal); Z_Free(portal);
} }
static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest) static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest, angle_t dangle)
{ {
// Offset the portal view by the linedef centers // Offset the portal view by the linedef centers
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
fixed_t disttopoint; fixed_t disttopoint;
angle_t angtopoint; angle_t angtopoint;
...@@ -168,7 +166,6 @@ static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t * ...@@ -168,7 +166,6 @@ static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *
portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle; portal->viewangle = viewangle + dangle;
} }
...@@ -189,12 +186,13 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con ...@@ -189,12 +186,13 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
line_t* start = &lines[line1]; line_t* start = &lines[line1];
line_t* dest = &lines[line2]; line_t* dest = &lines[line2];
Portal_GetViewpointForLine(portal, start, dest); angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
Portal_GetViewpointForLine(portal, start, dest, dangle);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->clipline = line2; portal->clipline = line2;
portal->is_skybox = false;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_ClipRange(portal); Portal_ClipRange(portal);
...@@ -317,10 +315,7 @@ static boolean Portal_AddSkybox (const visplane_t* plane) ...@@ -317,10 +315,7 @@ static boolean Portal_AddSkybox (const visplane_t* plane)
Portal_ClipVisplane(plane, portal); Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_skybox = true; portal->is_skybox = true;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSkybox(portal); Portal_GetViewpointForSkybox(portal);
...@@ -332,14 +327,28 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se ...@@ -332,14 +327,28 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
fixed_t x, y, z; fixed_t x, y, z;
angle_t angle; angle_t angle;
sector_t *target = secportal->target;
fixed_t target_x = target->soundorg.x;
fixed_t target_y = target->soundorg.y;
fixed_t target_z;
if (secportal->ceiling)
target_z = P_GetSectorCeilingZAt(target, target_x, target_y);
else
target_z = P_GetSectorFloorZAt(target, target_x, target_y);
switch (secportal->type) switch (secportal->type)
{ {
case SECPORTAL_LINE: case SECPORTAL_LINE:
Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest); angle = secportal->line.dest->angle - secportal->line.start->angle;
Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest, angle);
portal->viewz = viewz; // Apparently it just works like that. Not going to question it.
return; return;
case SECPORTAL_OBJECT: case SECPORTAL_OBJECT:
if (!secportal->mobj || P_MobjWasRemoved(secportal->mobj)) if (P_MobjWasRemoved(secportal->mobj))
return; return;
portal->viewmobj = secportal->mobj;
x = secportal->mobj->x; x = secportal->mobj->x;
y = secportal->mobj->y; y = secportal->mobj->y;
z = secportal->mobj->z; z = secportal->mobj->z;
...@@ -373,8 +382,9 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se ...@@ -373,8 +382,9 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
return; return;
} }
fixed_t refx = secportal->origin.x - viewx; fixed_t refx = target_x - viewx;
fixed_t refy = secportal->origin.y - viewy; fixed_t refy = target_y - viewy;
fixed_t refz = target_z - viewz;
// Rotate the X/Y to match the target angle // Rotate the X/Y to match the target angle
if (angle != 0) if (angle != 0)
...@@ -387,7 +397,7 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se ...@@ -387,7 +397,7 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
portal->viewx = x - refx; portal->viewx = x - refx;
portal->viewy = y - refy; portal->viewy = y - refy;
portal->viewz = z + viewz; portal->viewz = z - refz;
portal->viewangle = angle + viewangle; portal->viewangle = angle + viewangle;
} }
...@@ -413,11 +423,6 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane) ...@@ -413,11 +423,6 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane)
Portal_ClipVisplane(plane, portal); Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_horizon = false;
portal->is_skybox = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSecPortal(portal, secportal); Portal_GetViewpointForSecPortal(portal, secportal);
return true; return true;
...@@ -425,7 +430,7 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane) ...@@ -425,7 +430,7 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane)
/** Creates a transferred sector portal. /** Creates a transferred sector portal.
*/ */
void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) void Portal_AddTransferred (const UINT32 secportalnum, const INT32 x1, const INT32 x2)
{ {
if (secportalnum >= secportalcount) if (secportalnum >= secportalcount)
return; return;
...@@ -435,9 +440,6 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) ...@@ -435,9 +440,6 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2)
return; return;
portal_t* portal = Portal_Add(x1, x2); portal_t* portal = Portal_Add(x1, x2);
portal->is_skybox = false;
portal->is_horizon = false;
portal->horizon_sector = NULL;
if (secportal->type == SECPORTAL_SKYBOX) if (secportal->type == SECPORTAL_SKYBOX)
Portal_GetViewpointForSkybox(portal); Portal_GetViewpointForSkybox(portal);
......
...@@ -36,6 +36,8 @@ typedef struct portal_s ...@@ -36,6 +36,8 @@ typedef struct portal_s
boolean is_skybox; boolean is_skybox;
mobj_t *viewmobj;
UINT8 pass; /**< Keeps track of the portal's recursion depth. */ UINT8 pass; /**< Keeps track of the portal's recursion depth. */
INT32 clipline; /**< Optional clipline for line-based portals. */ INT32 clipline; /**< Optional clipline for line-based portals. */
...@@ -58,7 +60,7 @@ extern INT32 portalclipstart, portalclipend; ...@@ -58,7 +60,7 @@ extern INT32 portalclipstart, portalclipend;
void Portal_InitList (void); void Portal_InitList (void);
void Portal_Remove (portal_t* portal); void Portal_Remove (portal_t* portal);
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2); void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2); void Portal_AddTransferred (const UINT32 secportalnum, const INT32 x1, const INT32 x2);
void Portal_ClipRange (portal_t* portal); void Portal_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal); void Portal_ClipApply (const portal_t* portal);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -94,6 +94,124 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha) ...@@ -94,6 +94,124 @@ transnum_t R_GetLinedefTransTable(fixed_t alpha)
return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1);
} }
static UINT8 R_SideLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light +
((side->lightabsolute) ? 0 : base_lightlevel)));
}
/* TODO: implement per-texture lighting
static UINT8 R_TopLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_top +
((side->lightabsolute_top) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
static UINT8 R_MidLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_mid +
((side->lightabsolute_mid) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
static UINT8 R_BottomLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_bottom +
((side->lightabsolute_bottom) ? 0 : R_SideLightLevel(side, base_lightlevel))));
}
*/
// If we have a multi-patch texture on a 2sided wall (rare) then we draw
// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this
// way we don't have to store extra post_t info with each column for
// multi-patch textures. They are not normally needed as multi-patch
// textures don't have holes in it. At least not for now.
static void R_Render2sidedMultiPatchColumn(column_t *column, unsigned lengthcol)
{
INT32 topscreen, bottomscreen;
post_t *post = &column->posts[0];
if (!post->length)
return;
topscreen = sprtopscreen;
bottomscreen = topscreen + spryscale * lengthcol;
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
{
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
dc_yh = (windowbottom - 1)>>FRACBITS;
}
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x] - 1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1;
if (dc_yl >= vid.height || dc_yh < 0)
return;
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
{
dc_source = column->pixels + post->data_offset;
dc_postlength = post->length;
if (colfunc == colfuncs[BASEDRAWFUNC])
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])();
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
(colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])();
else
colfunc();
}
}
static void R_RenderFlipped2sidedMultiPatchColumn(column_t *column, unsigned lengthcol)
{
INT32 topscreen, bottomscreen;
void (*localcolfunc)(void);
post_t *post = &column->posts[0];
if (!post->length)
return;
topscreen = sprtopscreen;
bottomscreen = topscreen + spryscale * lengthcol;
dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (windowtop != INT32_MAX && windowbottom != INT32_MAX)
{
dc_yl = ((windowtop + FRACUNIT)>>FRACBITS);
dc_yh = (windowbottom - 1)>>FRACBITS;
}
if (dc_yh >= mfloorclip[dc_x])
dc_yh = mfloorclip[dc_x] - 1;
if (dc_yl <= mceilingclip[dc_x])
dc_yl = mceilingclip[dc_x] + 1;
if (dc_yl >= vid.height || dc_yh < 0)
return;
if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0)
{
dc_postlength = post->length;
if (colfunc == colfuncs[BASEDRAWFUNC])
localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCH];
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY])
localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS];
else
localcolfunc = colfunc;
R_DrawFlippedPost(column->pixels + post->data_offset, post->length, localcolfunc);
}
}
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{ {
size_t pindex; size_t pindex;
...@@ -181,7 +299,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -181,7 +299,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
// Texture must be cached // Texture must be cached
R_CheckTextureCache(texnum); R_CheckTextureCache(texnum);
// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
// are not stored per-column with post info in SRB2
if (!textures[texnum]->transparency)
{
if (vertflip) // vertically flipped? if (vertflip) // vertically flipped?
colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn;
else
colfunc_2s = R_Render2sidedMultiPatchColumn;
}
else if (vertflip) // vertically flipped?
colfunc_2s = R_DrawFlippedMaskedColumn; colfunc_2s = R_DrawFlippedMaskedColumn;
else else
colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
...@@ -223,7 +350,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -223,7 +350,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (rlight->flags & FOF_FOG) || (rlight->flags & FOF_FOG)
|| (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT;
else else
lightnum = LIGHTLEVELS - 1; lightnum = LIGHTLEVELS - 1;
...@@ -241,7 +368,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -241,7 +368,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
{ {
if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY])
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
else else
lightnum = LIGHTLEVELS - 1; lightnum = LIGHTLEVELS - 1;
...@@ -442,26 +569,75 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) ...@@ -442,26 +569,75 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
} }
// Loop through R_DrawMaskedColumn calls // Loop through R_DrawMaskedColumn calls
static fixed_t repeatscroll = 0;
static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol) static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol)
{ {
while (sprtopscreen < sprbotscreen) { fixed_t topscreen = sprtopscreen;
fixed_t bottomscreen = sprbotscreen;
fixed_t texheight = dc_texheight*spryscale;
fixed_t scroll = -repeatscroll;
if (scroll < 0)
{
scroll = -FixedMul((abs(scroll) % (dc_texheight*FRACUNIT)), spryscale);
bottomscreen += texheight; // Draw an extra time
}
else if (scroll)
{
scroll = FixedMul(scroll % (dc_texheight*FRACUNIT), spryscale);
topscreen -= texheight; // Draw an extra time
}
while (topscreen < bottomscreen)
{
sprtopscreen = topscreen + scroll;
R_DrawMaskedColumn(col, lengthcol); R_DrawMaskedColumn(col, lengthcol);
if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
sprtopscreen = INT32_MAX; break;
else
sprtopscreen += dc_texheight*spryscale; topscreen += texheight;
} }
sprtopscreen = sprbotscreen;
} }
static void R_DrawRepeatFlippedMaskedColumn(column_t *col, unsigned lengthcol) static void R_DrawRepeatFlippedMaskedColumn(column_t *col, unsigned lengthcol)
{ {
while (sprtopscreen < sprbotscreen) { fixed_t topscreen = sprtopscreen;
fixed_t bottomscreen = sprbotscreen;
fixed_t texheight = dc_texheight*spryscale;
fixed_t scroll = -repeatscroll;
if (scroll < 0)
{
scroll = -FixedMul((abs(scroll) % (dc_texheight*FRACUNIT)), spryscale);
bottomscreen += texheight; // Draw an extra time
}
else if (scroll)
{
scroll = FixedMul(scroll % (dc_texheight*FRACUNIT), spryscale);
topscreen -= texheight; // Draw an extra time
}
while (topscreen < bottomscreen)
{
sprtopscreen = topscreen + scroll;
sprbotscreen = bottomscreen + scroll;
R_DrawFlippedMaskedColumn(col, lengthcol); R_DrawFlippedMaskedColumn(col, lengthcol);
if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
sprtopscreen = INT32_MAX; break;
else
sprtopscreen += dc_texheight*spryscale; topscreen += texheight;
} }
sprtopscreen = sprbotscreen;
} }
// Returns true if a fake floor is translucent. // Returns true if a fake floor is translucent.
...@@ -497,7 +673,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -497,7 +673,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
sector_t tempsec; sector_t tempsec;
INT32 templight; INT32 templight;
INT32 i, p; INT32 i, p;
fixed_t offsetvalue;
lightlist_t *light; lightlist_t *light;
r_lightlist_t *rlight; r_lightlist_t *rlight;
INT32 range; INT32 range;
...@@ -515,6 +690,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -515,6 +690,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
fixed_t wall_scalex, wall_scaley; fixed_t wall_scalex, wall_scaley;
UINT8 vertflip; UINT8 vertflip;
unsigned lengthcol; unsigned lengthcol;
boolean fog = false;
boolean fuzzy = false;
void (*colfunc_2s) (column_t *, unsigned); void (*colfunc_2s) (column_t *, unsigned);
...@@ -526,13 +703,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -526,13 +703,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
curline = ds->curline; curline = ds->curline;
backsector = pfloor->target; backsector = pfloor->target;
frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
sidedef = R_GetFFloorSide(curline, pfloor); sidedef = R_GetFFloorSide(curline->linedef, pfloor, pfloor->target);
colfunc = colfuncs[BASEDRAWFUNC];
if (pfloor->master->flags & ML_TFERLINE) if (pfloor->master->flags & ML_TFERLINE)
{ {
line_t *newline = R_GetFFloorLine(curline, pfloor); line_t *newline = R_GetFFloorLine(curline->linedef, pfloor, pfloor->target);
do_texture_skew = newline->flags & ML_SKEWTD; do_texture_skew = newline->flags & ML_SKEWTD;
dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM;
} }
...@@ -547,7 +722,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -547,7 +722,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (pfloor->fofflags & FOF_TRANSLUCENT) if (pfloor->fofflags & FOF_TRANSLUCENT)
{ {
boolean fuzzy = true; fuzzy = true;
// Hacked up support for alpha value in software mode Tails 09-24-2002 // Hacked up support for alpha value in software mode Tails 09-24-2002
// ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021 // ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021
...@@ -560,17 +735,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -560,17 +735,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else if (!(dc_transmap = R_GetTranslucencyTable(trans)) || trans == 0) else if (!(dc_transmap = R_GetTranslucencyTable(trans)) || trans == 0)
fuzzy = false; // Opaque fuzzy = false; // Opaque
} }
if (fuzzy)
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
} }
else if (pfloor->fofflags & FOF_FOG) else if (pfloor->fofflags & FOF_FOG)
{
colfunc = colfuncs[COLDRAWFUNC_FOG]; colfunc = colfuncs[COLDRAWFUNC_FOG];
fog = true;
}
range = max(ds->x2-ds->x1, 1); range = max(ds->x2-ds->x1, 1);
//SoM: Moved these up here so they are available for my lightlist calculations
rw_scalestep = ds->scalestep;
spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
dc_numlights = 0; dc_numlights = 0;
if (frontsector->numlights) if (frontsector->numlights)
...@@ -652,9 +824,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -652,9 +824,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// Check if the current light effects the colormap/lightlevel // Check if the current light effects the colormap/lightlevel
if (pfloor->fofflags & FOF_FOG) if (pfloor->fofflags & FOF_FOG)
rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); rlight->lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT;
else else
rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); rlight->lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT;
if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
; ;
...@@ -672,14 +844,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -672,14 +844,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
{ {
// Get correct light level! // Get correct light level!
if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
else if (pfloor->fofflags & FOF_FOG) else if (fog)
lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT;
else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) else if (fuzzy)
lightnum = LIGHTLEVELS-1; lightnum = LIGHTLEVELS-1;
else else
lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) lightnum = R_SideLightLevel(curline->sidedef, R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)->lightlevel) >> LIGHTSEGSHIFT;
->lightlevel >> LIGHTSEGSHIFT;
if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))); if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)));
else if (curline->v1->y == curline->v2->y) else if (curline->v1->y == curline->v2->y)
...@@ -703,6 +874,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -703,6 +874,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
vertflip = !vertflip; vertflip = !vertflip;
} }
//SoM: Moved these up here so they are available for my lightlist calculations
// Lactozilla: Moved them back down
// This uses floating point math now, because the fixed-point imprecisions
// become more severe the bigger the texture is scaled.
double dwall_scaley = FixedToDouble(wall_scaley);
double scalestep = FixedToDouble(ds->scalestep) / dwall_scaley;
double yscale = (FixedToDouble(ds->scale1) + (x1 - ds->x1)*scalestep) / dwall_scaley;
thicksidecol = ffloortexturecolumn; thicksidecol = ffloortexturecolumn;
wall_offsetx = ds->offsetx + sidedef->offsetx_mid; wall_offsetx = ds->offsetx + sidedef->offsetx_mid;
...@@ -734,7 +913,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -734,7 +913,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else else
dc_texturemid = FixedMul(*pfloor->topheight - viewz, wall_scaley); dc_texturemid = FixedMul(*pfloor->topheight - viewz, wall_scaley);
offsetvalue = sidedef->rowoffset + sidedef->offsety_mid; repeatscroll = sidedef->rowoffset + sidedef->offsety_mid;
if (dont_peg_bottom) if (dont_peg_bottom)
{ {
...@@ -744,7 +923,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -744,7 +923,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
dc_texturemid = FixedMul(left_bottom, wall_scaley); dc_texturemid = FixedMul(left_bottom, wall_scaley);
} }
else else
offsetvalue -= FixedMul(*pfloor->topheight - *pfloor->bottomheight, wall_scaley); repeatscroll -= FixedMul(*pfloor->topheight - *pfloor->bottomheight, wall_scaley);
} }
if (skewslope) if (skewslope)
...@@ -753,12 +932,21 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -753,12 +932,21 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
ffloortextureslide = FixedMul(R_GetSlopeTextureSlide(skewslope, lineangle), wall_scaley); ffloortextureslide = FixedMul(R_GetSlopeTextureSlide(skewslope, lineangle), wall_scaley);
} }
dc_texturemid += offsetvalue; dc_texturemid += repeatscroll;
// Texture must be cached // Texture must be cached
R_CheckTextureCache(texnum); R_CheckTextureCache(texnum);
// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
// are not stored per-column with post info in SRB2
if (!textures[texnum]->transparency)
{
if (vertflip) // vertically flipped? if (vertflip) // vertically flipped?
colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn;
else
colfunc_2s = R_Render2sidedMultiPatchColumn;
}
else if (vertflip) // vertically flipped?
colfunc_2s = R_DrawRepeatFlippedMaskedColumn; colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
else else
colfunc_2s = R_DrawRepeatMaskedColumn; colfunc_2s = R_DrawRepeatMaskedColumn;
...@@ -824,15 +1012,41 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -824,15 +1012,41 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
rlight->botheight += rlight->botheightstep; rlight->botheight += rlight->botheightstep;
} }
} }
spryscale += rw_scalestep; yscale += scalestep;
continue; continue;
} }
dc_iscale = FixedMul(0xffffffffu / (unsigned)spryscale, wall_scaley);
// Get data for the column // Get data for the column
col = R_GetColumn(texnum, ((thicksidecol[dc_x] + wall_offsetx) >> FRACBITS)); col = R_GetColumn(texnum, ((thicksidecol[dc_x] + wall_offsetx) >> FRACBITS));
spryscale = DoubleToFixed(yscale);
// Eh. I tried fixing the scaling artifacts but it still wasn't perfect.
// So this checks if the column has gaps in it or not, and if it does, uses a version of the column drawers
// that prevents the artifacts from being visible.
// Note that if rendering fog then none of this matters because there's no texture mapping to be done
if (!fog)
{
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// Column has a single post and it matches the texture height, use regular column drawers
if (col->num_posts == 1 && col->posts[0].topdelta == 0 && col->posts[0].length == (unsigned)dc_texheight)
{
if (fuzzy)
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
else
colfunc = colfuncs[BASEDRAWFUNC];
}
else
{
// Otherwise use column drawers with extra checks
if (fuzzy)
colfunc = colfuncs[COLDRAWFUNC_CLAMPEDTRANS];
else
colfunc = colfuncs[COLDRAWFUNC_CLAMPED];
}
}
// SoM: New code does not rely on R_DrawColumnShadowed_8 which // SoM: New code does not rely on R_DrawColumnShadowed_8 which
// will (hopefully) put less strain on the stack. // will (hopefully) put less strain on the stack.
if (dc_numlights) if (dc_numlights)
...@@ -947,7 +1161,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -947,7 +1161,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (windowtop < windowbottom) if (windowtop < windowbottom)
colfunc_2s (col, lengthcol); colfunc_2s (col, lengthcol);
spryscale += rw_scalestep; yscale += scalestep;
continue; continue;
} }
...@@ -966,7 +1180,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ...@@ -966,7 +1180,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
// draw the texture // draw the texture
colfunc_2s (col, lengthcol); colfunc_2s (col, lengthcol);
spryscale += rw_scalestep; yscale += scalestep;
} }
colfunc = colfuncs[BASEDRAWFUNC]; colfunc = colfuncs[BASEDRAWFUNC];
...@@ -1274,7 +1488,7 @@ static void R_RenderSegLoop (void) ...@@ -1274,7 +1488,7 @@ static void R_RenderSegLoop (void)
for (i = 0; i < dc_numlights; i++) for (i = 0; i < dc_numlights; i++)
{ {
INT32 lightnum; INT32 lightnum;
lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, dc_lightlist[i].lightlevel) >> LIGHTSEGSHIFT;
if (dc_lightlist[i].extra_colormap) if (dc_lightlist[i].extra_colormap)
; ;
...@@ -2461,7 +2675,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ...@@ -2461,7 +2675,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// use different light tables // use different light tables
// for horizontal / vertical / diagonal // for horizontal / vertical / diagonal
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT;
if (curline->v1->y == curline->v2->y) if (curline->v1->y == curline->v2->y)
lightnum--; lightnum--;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "p_local.h" #include "p_local.h"
#include "dehacked.h" // get_number (for thok) #include "dehacked.h" // get_number (for thok)
#include "m_cond.h" #include "m_cond.h"
#include "deh_tables.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_md2.h" #include "hardware/hw_md2.h"
#endif #endif
...@@ -43,10 +44,9 @@ UINT16 P_GetStateSprite2(state_t *state) ...@@ -43,10 +44,9 @@ UINT16 P_GetStateSprite2(state_t *state)
else else
{ {
// Transform the state frame into an animation ID // Transform the state frame into an animation ID
UINT32 stateframe = state->frame & FF_FRAMEMASK; UINT16 spr2 = state->frame & FF_FRAMEMASK;
UINT16 spr2 = stateframe & ~FF_SPR2SUPER;
if (stateframe & FF_SPR2SUPER) if (state->frame & SPR2F_SUPER)
spr2 |= SPR2F_SUPER; spr2 |= SPR2F_SUPER;
return spr2; return spr2;
...@@ -70,7 +70,7 @@ boolean P_IsStateSprite2Super(state_t *state) ...@@ -70,7 +70,7 @@ boolean P_IsStateSprite2Super(state_t *state)
if (state->sprite2 & SPR2F_SUPER) if (state->sprite2 & SPR2F_SUPER)
return true; return true;
} }
else if (state->frame & FF_SPR2SUPER) else if (state->frame & SPR2F_SUPER)
return true; return true;
return false; return false;
...@@ -81,10 +81,19 @@ UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj) ...@@ -81,10 +81,19 @@ UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj)
{ {
if (mobj->player) if (mobj->player)
{ {
if (mobj->player->charflags & SF_NOSUPERSPRITES || (mobj->player->powers[pw_carry] == CR_NIGHTSMODE && (mobj->player->charflags & SF_NONIGHTSSUPER))) boolean is_nights = mobj->player->powers[pw_carry] == CR_NIGHTSMODE;
if (mobj->player->charflags & SF_NOSUPERSPRITES || (is_nights && (mobj->player->charflags & SF_NONIGHTSSUPER)))
spr2 &= ~SPR2F_SUPER; spr2 &= ~SPR2F_SUPER;
else if (mobj->player->powers[pw_super] || (mobj->player->powers[pw_carry] == CR_NIGHTSMODE && (mobj->player->charflags & SF_SUPER))) else if (mobj->player->powers[pw_super] || (is_nights && (mobj->player->charflags & SF_SUPER)))
spr2 |= SPR2F_SUPER; spr2 |= SPR2F_SUPER;
// Special case for transforming when you are NiGHTS.
// Do NOT apply the super sprites in this situation, even if they exist.
if (is_nights && mobj->state >= &states[S_PLAY_NIGHTS_TRANS1] && mobj->state <= &states[S_PLAY_NIGHTS_TRANS6])
{
spr2 &= ~SPR2F_SUPER;
}
} }
if (spr2 & SPR2F_SUPER) if (spr2 & SPR2F_SUPER)
...@@ -637,6 +646,14 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski ...@@ -637,6 +646,14 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
if (skin->sprites[0].numframes == 0) if (skin->sprites[0].numframes == 0)
CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]); CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]);
// TODO: 2.3: Delete
memcpy(&skin->sprites_compat[start_spr2],
&skin->sprites[start_spr2],
sizeof(spritedef_t) * (free_spr2 - start_spr2));
memcpy(&skin->sprites_compat[start_spr2 + NUMPLAYERSPRITES],
&skin->super.sprites[start_spr2],
sizeof(spritedef_t) * (free_spr2 - start_spr2));
} }
// returns whether found appropriate property // returns whether found appropriate property
...@@ -723,6 +740,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) ...@@ -723,6 +740,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
GETFLAG(MACHINE) GETFLAG(MACHINE)
GETFLAG(DASHMODE) GETFLAG(DASHMODE)
GETFLAG(FASTEDGE) GETFLAG(FASTEDGE)
GETFLAG(FASTWAIT)
GETFLAG(JETFUME)
GETFLAG(MULTIABILITY) GETFLAG(MULTIABILITY)
GETFLAG(NONIGHTSROTATION) GETFLAG(NONIGHTSROTATION)
GETFLAG(NONIGHTSSUPER) GETFLAG(NONIGHTSSUPER)
...@@ -773,6 +792,88 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) ...@@ -773,6 +792,88 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
return true; return true;
} }
// e.g. "RUN" => S_PLAY_RUN, "RUN1" => S_PLAY_RUN, "RUN8" => S_PLAY_RUN
static statenum_t GetCanonicalPlayerStateNumByName(const char *name)
{
if (startswith(name, "STAND")) return S_PLAY_STND;
else if (startswith(name, "STND")) return S_PLAY_STND;
else if (startswith(name, "WAIT")) return S_PLAY_WAIT;
else if (startswith(name, "WALK")) return S_PLAY_WALK;
else if (startswith(name, "SKID")) return S_PLAY_SKID;
else if (startswith(name, "RUN")) return S_PLAY_RUN;
else if (startswith(name, "DASH")) return S_PLAY_DASH;
else if (startswith(name, "PAIN")) return S_PLAY_PAIN;
else if (startswith(name, "STUN")) return S_PLAY_STUN;
else if (startswith(name, "DEAD")) return S_PLAY_DEAD;
else if (startswith(name, "DRWN")) return S_PLAY_DRWN;
else if (startswith(name, "ROLL")) return S_PLAY_ROLL;
else if (startswith(name, "GASP")) return S_PLAY_GASP;
else if (startswith(name, "JUMP")) return S_PLAY_JUMP;
else if (startswith(name, "SPRING")) return S_PLAY_SPRING;
else if (startswith(name, "FALL")) return S_PLAY_FALL;
else if (startswith(name, "EDGE")) return S_PLAY_EDGE;
else if (startswith(name, "RIDE")) return S_PLAY_RIDE;
else if (startswith(name, "SPINDASH")) return S_PLAY_SPINDASH;
else if (startswith(name, "FLY")) return S_PLAY_FLY;
else if (startswith(name, "SWIM")) return S_PLAY_SWIM;
else if (startswith(name, "FLY_TIRED")) return S_PLAY_FLY_TIRED;
else if (startswith(name, "GLIDE")) return S_PLAY_GLIDE;
else if (startswith(name, "GLIDE_LANDING")) return S_PLAY_GLIDE_LANDING;
else if (startswith(name, "CLING")) return S_PLAY_CLING;
else if (startswith(name, "CLIMB")) return S_PLAY_CLIMB;
else if (startswith(name, "FLOAT")) return S_PLAY_FLOAT;
else if (startswith(name, "FLOAT_RUN")) return S_PLAY_FLOAT_RUN;
else if (startswith(name, "BOUNCE")) return S_PLAY_BOUNCE;
else if (startswith(name, "BOUNCE_LANDING")) return S_PLAY_BOUNCE_LANDING;
else if (startswith(name, "FIRE")) return S_PLAY_FIRE;
else if (startswith(name, "FIRE_FINISH")) return S_PLAY_FIRE_FINISH;
else if (startswith(name, "TWINSPIN")) return S_PLAY_TWINSPIN;
else if (startswith(name, "MELEE")) return S_PLAY_MELEE;
else if (startswith(name, "MELEE_FINISH")) return S_PLAY_MELEE_FINISH;
else if (startswith(name, "MELEE_LANDING")) return S_PLAY_MELEE_LANDING;
else if (startswith(name, "NIGHTS_STAND")) return S_PLAY_NIGHTS_STAND;
else if (startswith(name, "NIGHTS_FLOAT")) return S_PLAY_NIGHTS_FLOAT;
else if (startswith(name, "NIGHTS_FLY")) return S_PLAY_NIGHTS_FLY;
else if (startswith(name, "NIGHTS_DRILL")) return S_PLAY_NIGHTS_DRILL;
else if (startswith(name, "NIGHTS_STUN")) return S_PLAY_NIGHTS_STUN;
else if (startswith(name, "NIGHTS_PULL")) return S_PLAY_NIGHTS_PULL;
else if (startswith(name, "NIGHTS_ATTACK")) return S_PLAY_NIGHTS_ATTACK;
else return S_NULL;
}
static void CacheCustomSkinStates(skin_t *skin)
{
SIMPLEHASH_CLEAR(skin->defaulttocustomstate, hashentry_int32_int32_t)
SIMPLEHASH_CLEAR(skin->customtodefaultstate, hashentry_int32_int32_t)
char *skinstateprefix = va("SKIN_%s_", skin->name);
strupr(skinstateprefix);
size_t skinstateprefixlen = strlen(skinstateprefix);
for (INT32 state = S_FIRSTFREESLOT; state <= S_LASTFREESLOT; state++)
{
const char *statename = FREE_STATES[state - S_FIRSTFREESLOT];
if (!statename)
continue;
if (strncmp(statename, skinstateprefix, skinstateprefixlen))
continue;
statenum_t defaultstate = GetCanonicalPlayerStateNumByName(&statename[skinstateprefixlen]);
if (defaultstate)
{
// If a default state is overriden by multiple custom states, use the first one as reference
// e.g. WALK+WALK2+WALK3+WALK4 instead of just WALK
statenum_t alreadyoverriden;
SIMPLEHASH_FIND_INT(skin->defaulttocustomstate, hashentry_int32_int32_t, defaultstate, S_NULL, alreadyoverriden)
if (!alreadyoverriden)
SIMPLEHASH_REPLACE_INT(skin->defaulttocustomstate, hashentry_int32_int32_t, defaultstate, state)
SIMPLEHASH_REPLACE_INT(skin->customtodefaultstate, hashentry_int32_int32_t, state, defaultstate)
}
}
}
// //
// Find skin sprites, sounds & optional status bar face, & add them // Find skin sprites, sounds & optional status bar face, & add them
// //
...@@ -927,6 +1028,8 @@ next_token: ...@@ -927,6 +1028,8 @@ next_token:
R_FlushTranslationColormapCache(); R_FlushTranslationColormapCache();
CacheCustomSkinStates(skin);
if (mainfile == false) if (mainfile == false)
CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name);
...@@ -1064,6 +1167,8 @@ next_token: ...@@ -1064,6 +1167,8 @@ next_token:
R_FlushTranslationColormapCache(); R_FlushTranslationColormapCache();
CacheCustomSkinStates(skin);
if (mainfile == false) if (mainfile == false)
CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name);
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "r_patch.h" #include "r_patch.h"
#include "r_picformats.h" // spriteinfo_t #include "r_picformats.h" // spriteinfo_t
#include "r_defs.h" // spritedef_t #include "r_defs.h" // spritedef_t
#include "simple_hashmap.h"
/// Defaults /// Defaults
#define SKINNAMESIZE 16 #define SKINNAMESIZE 16
...@@ -88,6 +89,12 @@ typedef struct ...@@ -88,6 +89,12 @@ typedef struct
spritedef_t sprites[NUMPLAYERSPRITES]; spritedef_t sprites[NUMPLAYERSPRITES];
spriteinfo_t sprinfo[NUMPLAYERSPRITES]; spriteinfo_t sprinfo[NUMPLAYERSPRITES];
} super; } super;
hashentry_int32_int32_t *defaulttocustomstate; // e.g. S_PLAY_WALK => S_SKIN_BIGTHECAT_WALK
hashentry_int32_int32_t *customtodefaultstate; // e.g. S_SKIN_BIGTHECAT_WALK => S_PLAY_WALK
// TODO: 2.3: Delete
spritedef_t sprites_compat[NUMPLAYERSPRITES * 2];
} skin_t; } skin_t;
/// Externs /// Externs
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
......