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
  • better-distance-math
  • 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
  • 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
  • voltybystorm/SRB2
118 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
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • PS3
  • 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-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
  • 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
  • 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-debug-library
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • 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
......@@ -72,7 +72,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
#define NUMCOLORMAPS 32
// Utility functions.
INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node);
INT32 R_PointOnSide(fixed_t x, fixed_t y, bspnode_t *node);
INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line);
angle_t R_PointToAngle(fixed_t x, fixed_t y);
angle_t R_PointToAngle64(INT64 x, INT64 y);
......
......@@ -31,14 +31,12 @@ patch_t *Patch_Create(INT16 width, INT16 height)
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 (!source)
return patch;
if (!Picture_CheckIfDoomPatch(source, insize))
return NULL;
patch->width = SHORT(source->width);
patch->height = SHORT(source->height);
patch_t *patch = Patch_Create(SHORT(source->width), SHORT(source->height));
patch->leftoffset = SHORT(source->leftoffset);
patch->topoffset = SHORT(source->topoffset);
......
......@@ -19,7 +19,7 @@
// Patch functions
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_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);
......
......@@ -54,12 +54,26 @@ INT32 R_GetRollAngle(angle_t rollangle)
patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip)
{
rotsprite_t *rotsprite = patch->rotated;
if (rotsprite == NULL || angle < 1 || angle >= ROTANGLES)
if (angle < 1 || angle >= ROTANGLES)
return NULL;
if (rotsprite == NULL)
{
rotsprite = RotatedPatch_Create(ROTANGLES);
patch->rotated = rotsprite;
}
if (flip)
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];
}
......
......@@ -87,7 +87,12 @@ void *Picture_Convert(
(void)insize;
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))
return Picture_FlatConvert(informat, picture, outformat, outsize, inwidth, intopoffset, flags);
else
......@@ -235,8 +240,8 @@ static void *WritePatchPixel_i8o8(void *ptr, void *input)
* \return A pointer to the converted picture.
*/
void *Picture_PatchConvert(
pictureformat_t informat, void *picture, pictureformat_t outformat,
size_t *outsize,
pictureformat_t informat, size_t insize, void *picture,
pictureformat_t outformat, size_t *outsize,
INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset,
pictureflags_t flags)
{
......@@ -245,7 +250,7 @@ void *Picture_PatchConvert(
{
if (outsize != NULL)
*outsize = sizeof(patch_t);
return Patch_CreateFromDoomPatch(picture);
return Patch_CreateFromDoomPatch(picture, insize);
}
INT32 outbpp = Picture_FormatBPP(outformat);
......@@ -799,47 +804,44 @@ boolean Picture_IsFlatFormat(pictureformat_t format)
}
/** Returns true if the lump is a valid Doom patch.
* PICFMT_DOOMPATCH only.
*
* \param patch Input patch.
* \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)
{
INT16 width, height;
boolean result;
// Does not meet minimum size requirements
if (size < MIN_PATCH_LUMP_SIZE)
return false;
// minimum length of a valid Doom patch
if (size < 13)
INT16 width = SHORT(patch->width);
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;
width = SHORT(patch->width);
height = SHORT(patch->height);
result = (height > 0 && height <= 16384 && width > 0 && width <= 16384);
// Lump size makes no sense given the width
if (!VALID_PATCH_LUMP_SIZE(size, width))
return false;
if (result)
{
// The dimensions seem like they might be valid for a patch, so
// check the column directory for extra security. All columns
// must begin after the column directory, and none of them must
// point past the end of the patch.
INT16 x;
for (x = 0; x < width; x++)
for (INT16 x = 0; x < width; x++)
{
UINT32 ofs = LONG(patch->columnofs[x]);
// 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;
break;
}
return false;
}
}
return result;
return true;
}
/** Converts a texture to a flat.
......@@ -901,12 +903,13 @@ void *Picture_TextureToFlat(size_t texnum)
*/
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;
// Check for PNG file signature using memcmp
// 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
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
......@@ -1373,7 +1376,9 @@ void *Picture_PNGConvert(
}
// 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);
return converted;
}
......
......@@ -55,6 +55,29 @@ enum
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(
pictureformat_t informat, void *picture, pictureformat_t outformat,
size_t insize, size_t *outsize,
......@@ -62,8 +85,8 @@ void *Picture_Convert(
pictureflags_t flags);
void *Picture_PatchConvert(
pictureformat_t informat, void *picture, pictureformat_t outformat,
size_t *outsize,
pictureformat_t informat, size_t insize, void *picture,
pictureformat_t outformat, size_t *outsize,
INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset,
pictureflags_t flags);
void *Picture_FlatConvert(
......@@ -104,9 +127,6 @@ typedef struct
boolean available;
} spriteinfo_t;
// PNG support
#define PNG_HEADER_SIZE 8
boolean Picture_IsLumpPNG(const UINT8 *d, size_t s);
#ifndef NO_PNG_LUMPS
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2024 by Sonic Team Junior.
// Copyright (C) 1999-2025 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -83,7 +83,7 @@ static fixed_t planeheight;
fixed_t yslopetab[MAXVIDHEIGHT*16];
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_lightu, slope_lightv;
......@@ -182,8 +182,8 @@ static void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
R_CalculatePlaneRipple(currentplane->viewangle + currentplane->plangle);
ds_xfrac += planeripple.xfrac;
ds_yfrac += planeripple.yfrac;
ds_xfrac += FixedMul(planeripple.xfrac, currentplane->xscale);
ds_yfrac += FixedMul(planeripple.yfrac, currentplane->yscale);
ds_bgofs >>= FRACBITS;
if ((y + ds_bgofs) >= viewheight)
......@@ -376,19 +376,25 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li
visplane_t *check;
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
{
xoff += FixedMul(viewx, xscale);
yoff -= FixedMul(viewy, yscale);
offset_x += viewx;
offset_y -= viewy;
if (plangle != 0)
{
// Add the view offset, rotated by the plane angle.
float ang = ANG2RAD(plangle);
float x = FixedToFloat(xoff);
float y = FixedToFloat(yoff);
xoff = FloatToFixed(x * cos(ang) + y * sin(ang));
yoff = FloatToFixed(-x * sin(ang) + y * cos(ang));
float x = offset_x / (float)FRACUNIT;
float y = offset_y / (float)FRACUNIT;
offset_x = (x * cos(ang) + y * sin(ang)) * FRACUNIT;
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
float ang = ANG2RAD(polyobj->angle);
float x = FixedToFloat(polyobj->centerPt.x);
float y = FixedToFloat(polyobj->centerPt.y);
xoff -= FloatToFixed(x * cos(ang) + y * sin(ang));
yoff -= FloatToFixed(x * sin(ang) - y * cos(ang));
offset_x -= (x * cos(ang) + y * sin(ang)) * FRACUNIT;
offset_y -= (x * sin(ang) - y * cos(ang)) * FRACUNIT;
}
else
{
xoff -= polyobj->centerPt.x;
yoff += polyobj->centerPt.y;
offset_x -= polyobj->centerPt.x;
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.
if (picnum == skyflatnum && pfloor)
{
......@@ -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
&& lightlevel == check->lightlevel
&& xoff == check->xoffs && yoff == check->yoffs
&& offset_x == check->xoffs && offset_y == check->yoffs
&& xscale == check->xscale && yscale == check->yscale
&& planecolormap == check->extra_colormap
&& 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
check->lightlevel = lightlevel;
check->minx = vid.width;
check->maxx = -1;
check->xoffs = xoff;
check->yoffs = yoff;
check->xoffs = offset_x;
check->yoffs = offset_y;
check->xscale = xscale;
check->yscale = yscale;
check->extra_colormap = planecolormap;
......@@ -658,13 +667,13 @@ static void R_DrawSkyPlane(visplane_t *pl)
}
// 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:
// (d + a*x + b*y) * -(1.0 / c)
double px = FixedToDouble(x) - slope->dorigin.x;
double py = FixedToDouble(y) - slope->dorigin.y;
double px = (x / (double)FRACUNIT) - slope->dorigin.x;
double py = (y / (double)FRACUNIT) - slope->dorigin.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)
}
// 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 vy = (INT64)ypos - (INT64)yoff;
INT64 vx = (INT64)xpos + xoff;
INT64 vy = (INT64)ypos - yoff;
float vxf = vx / (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,
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);
zeroheight = height - FixedToDouble(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.
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;
float ang;
......@@ -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))
{
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,
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
R_SetSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, xoff, yoff, pl->viewangle, pl->plangle);
......@@ -1079,6 +1090,9 @@ void R_DrawSinglePlane(visplane_t *pl)
case SPANDRAWFUNC_SPLAT:
spanfunctype = SPANDRAWFUNC_TILTEDSPLAT;
break;
case SPANDRAWFUNC_TRANSSPLAT:
spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPLAT;
break;
case SPANDRAWFUNC_SOLID:
spanfunctype = SPANDRAWFUNC_TILTEDSOLID;
break;
......
......@@ -48,7 +48,7 @@ typedef struct visplane_s
UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend;
INT32 high, low; // R_PlaneBounds should set these.
fixed_t xoffs, yoffs; // Scrolling flats.
INT64 xoffs, yoffs; // Scrolling flats.
fixed_t xscale, yscale;
sector_t *sector;
......@@ -85,7 +85,7 @@ void R_DrawSinglePlane(visplane_t *pl);
// 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_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
{
......
......@@ -101,7 +101,7 @@ void Portal_ClipApply (const portal_t* portal)
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 *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);
......@@ -117,7 +117,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
portal_cap->next = portal;
portal_cap = portal;
}
portal->next = NULL;
portal->clipline = -1;
// Store clipping values so they can be restored once the portal is rendered.
portal->ceilingclip = ceilingclipsave;
......@@ -142,11 +142,9 @@ void Portal_Remove (portal_t* 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
angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0);
fixed_t disttopoint;
angle_t angtopoint;
......@@ -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->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint);
portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight;
portal->viewangle = viewangle + dangle;
}
......@@ -189,12 +186,13 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con
line_t* start = &lines[line1];
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->is_skybox = false;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_ClipRange(portal);
......@@ -317,10 +315,7 @@ static boolean Portal_AddSkybox (const visplane_t* plane)
Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_skybox = true;
portal->is_horizon = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSkybox(portal);
......@@ -332,14 +327,28 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
fixed_t x, y, z;
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)
{
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;
case SECPORTAL_OBJECT:
if (!secportal->mobj || P_MobjWasRemoved(secportal->mobj))
if (P_MobjWasRemoved(secportal->mobj))
return;
portal->viewmobj = secportal->mobj;
x = secportal->mobj->x;
y = secportal->mobj->y;
z = secportal->mobj->z;
......@@ -373,8 +382,9 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
return;
}
fixed_t refx = secportal->origin.x - viewx;
fixed_t refy = secportal->origin.y - viewy;
fixed_t refx = target_x - viewx;
fixed_t refy = target_y - viewy;
fixed_t refz = target_z - viewz;
// Rotate the X/Y to match the target angle
if (angle != 0)
......@@ -387,7 +397,7 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se
portal->viewx = x - refx;
portal->viewy = y - refy;
portal->viewz = z + viewz;
portal->viewz = z - refz;
portal->viewangle = angle + viewangle;
}
......@@ -413,11 +423,6 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane)
Portal_ClipVisplane(plane, portal);
portal->clipline = -1;
portal->is_horizon = false;
portal->is_skybox = false;
portal->horizon_sector = NULL;
Portal_GetViewpointForSecPortal(portal, secportal);
return true;
......@@ -425,7 +430,7 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane)
/** 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)
return;
......@@ -435,9 +440,6 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2)
return;
portal_t* portal = Portal_Add(x1, x2);
portal->is_skybox = false;
portal->is_horizon = false;
portal->horizon_sector = NULL;
if (secportal->type == SECPORTAL_SKYBOX)
Portal_GetViewpointForSkybox(portal);
......
......@@ -36,6 +36,8 @@ typedef struct portal_s
boolean is_skybox;
mobj_t *viewmobj;
UINT8 pass; /**< Keeps track of the portal's recursion depth. */
INT32 clipline; /**< Optional clipline for line-based portals. */
......@@ -58,7 +60,7 @@ extern INT32 portalclipstart, portalclipend;
void Portal_InitList (void);
void Portal_Remove (portal_t* portal);
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_ClipApply (const portal_t* portal);
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2024 by Sonic Team Junior.
// Copyright (C) 1999-2025 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -28,6 +28,7 @@
#include "p_local.h"
#include "dehacked.h" // get_number (for thok)
#include "m_cond.h"
#include "deh_tables.h"
#ifdef HWRENDER
#include "hardware/hw_md2.h"
#endif
......@@ -80,10 +81,19 @@ UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj)
{
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;
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;
// 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)
......@@ -730,6 +740,8 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
GETFLAG(MACHINE)
GETFLAG(DASHMODE)
GETFLAG(FASTEDGE)
GETFLAG(FASTWAIT)
GETFLAG(JETFUME)
GETFLAG(MULTIABILITY)
GETFLAG(NONIGHTSROTATION)
GETFLAG(NONIGHTSSUPER)
......@@ -780,6 +792,88 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
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
//
......@@ -934,6 +1028,8 @@ next_token:
R_FlushTranslationColormapCache();
CacheCustomSkinStates(skin);
if (mainfile == false)
CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name);
......@@ -1071,6 +1167,8 @@ next_token:
R_FlushTranslationColormapCache();
CacheCustomSkinStates(skin);
if (mainfile == false)
CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name);
}
......
......@@ -20,6 +20,7 @@
#include "r_patch.h"
#include "r_picformats.h" // spriteinfo_t
#include "r_defs.h" // spritedef_t
#include "simple_hashmap.h"
/// Defaults
#define SKINNAMESIZE 16
......@@ -89,6 +90,9 @@ typedef struct
spriteinfo_t sprinfo[NUMPLAYERSPRITES];
} 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;
......
......@@ -53,7 +53,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
if (dir == 0)
{
for (;;)
for (; count > 0; count--)
{
rastertab[y1].maxx = xs;
rastertab[y1].tx2 = xe;
......@@ -62,13 +62,11 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
xs += dx0;
xe += dx1;
y1++;
if (count-- < 1) break;
}
}
else
{
for (;;)
for (; count > 0; count--)
{
rastertab[y1].maxx = xs;
rastertab[y1].tx2 = tc;
......@@ -77,8 +75,6 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
xs += dx0;
xe += dx1;
y1++;
if (count-- < 1) break;
}
}
}
......@@ -95,7 +91,7 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
if (dir == 0)
{
for (;;)
for (; count > 0; count--)
{
rastertab[y2].minx = xs;
rastertab[y2].tx1 = xe;
......@@ -104,13 +100,11 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
xs += dx0;
xe += dx1;
y2++;
if (count-- < 1) break;
}
}
else
{
for (;;)
for (; count > 0; count--)
{
rastertab[y2].minx = xs;
rastertab[y2].tx1 = tc;
......@@ -119,8 +113,6 @@ static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32
xs += dx0;
xe += dx1;
y2++;
if (count-- < 1) break;
}
}
}
......@@ -381,7 +373,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
if (pSplat->slope)
{
R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle);
R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, (INT64)pSplat->xscale, (INT64)pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle);
}
else if (!ds_solidcolor)
{
......
......@@ -71,7 +71,7 @@ extern size_t numsubsectors;
extern subsector_t *subsectors;
extern size_t numnodes;
extern node_t *nodes;
extern bspnode_t *nodes;
extern size_t numlines;
extern line_t *lines;
......
......@@ -430,6 +430,10 @@ UINT8 *R_GenerateTexture(size_t texnum)
realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH);
}
// Well, it's not valid...
if (realpatch == NULL)
continue;
x1 = patch->originx;
width = realpatch->width;
height = realpatch->height;
......@@ -925,7 +929,7 @@ Rloadtextures (INT32 i, INT32 w)
// printf("\"%s\" (wad: %u, lump: %u) is a single patch, dimensions %d x %d\n",W_CheckNameForNumPwad(wadnum,lumpnum),wadnum,lumpnum,width,height);
R_AddSinglePatchTexture(i, wadnum, lumpnum, width, height, TEXTURETYPE_SINGLEPATCH);
R_AddSinglePatchTexture(i, wadnum, lumpnum, width, height, TEXTURETYPE_TEXTURE);
i++;
}
......@@ -1494,7 +1498,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture)
resultTexture->hash = quickncasehash(newTextureName, 8);
resultTexture->width = newTextureWidth;
resultTexture->height = newTextureHeight;
resultTexture->type = TEXTURETYPE_COMPOSITE;
resultTexture->type = TEXTURETYPE_TEXTURE;
}
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
......@@ -1680,7 +1684,7 @@ static void AddTextureToCache(const char *name, UINT32 hash, INT32 id, UINT8 typ
//
// Check whether texture is available. Filter out NoTexture indicator.
//
INT32 R_CheckTextureNumForName(const char *name)
INT32 R_CheckTextureNumForName(const char *name, UINT8 type)
{
INT32 i;
UINT32 hash;
......@@ -1692,14 +1696,14 @@ INT32 R_CheckTextureNumForName(const char *name)
hash = quickncasehash(name, 8);
for (i = 0; i < tidcachelen; i++)
if (tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8))
if (tidcache[i].type == type && tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8))
return tidcache[i].id;
// Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier
for (i = numtextures - 1; i >= 0; i--)
if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8))
if (textures[i]->type == type && textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8))
{
AddTextureToCache(name, hash, i, textures[i]->type);
AddTextureToCache(name, hash, i, type);
return i;
}
......@@ -1738,47 +1742,29 @@ const char *R_TextureNameForNum(INT32 num)
//
// R_TextureNumForName
//
// Calls R_CheckTextureNumForName, aborts with error message.
// Calls R_CheckTextureNumForName. Returns REDWALL if not found.
//
INT32 R_TextureNumForName(const char *name)
{
const INT32 i = R_CheckTextureNumForName(name);
INT32 i = R_CheckTextureNumForName(name, TEXTURETYPE_TEXTURE);
// Didn't find it, so look for a flat
if (i == -1)
{
i = R_CheckTextureNumForName(name, TEXTURETYPE_FLAT);
}
// Still didn't find it, so return REDWALL
if (i == -1)
{
static INT32 redwall = -2;
CONS_Debug(DBG_SETUP, "WARNING: R_TextureNumForName: %.8s not found\n", name);
if (redwall == -2)
redwall = R_CheckTextureNumForName("REDWALL");
redwall = R_CheckTextureNumForName("REDWALL", TEXTURETYPE_TEXTURE);
if (redwall != -1)
return redwall;
return 1;
}
return i;
}
// Like R_CheckTextureNumForName, but only looks in the flat namespace specifically.
INT32 R_CheckFlatNumForName(const char *name)
{
INT32 i;
UINT32 hash;
// "NoTexture" marker.
if (name[0] == '-')
return 0;
hash = quickncasehash(name, 8);
for (i = 0; i < tidcachelen; i++)
if (tidcache[i].type == TEXTURETYPE_FLAT && tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8))
return tidcache[i].id;
for (i = numtextures - 1; i >= 0; i--)
if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8) && textures[i]->type == TEXTURETYPE_FLAT)
{
AddTextureToCache(name, hash, i, TEXTURETYPE_FLAT);
return i;
}
return -1;
}
......@@ -40,8 +40,7 @@ typedef struct
enum
{
TEXTURETYPE_UNKNOWN,
TEXTURETYPE_SINGLEPATCH,
TEXTURETYPE_COMPOSITE,
TEXTURETYPE_TEXTURE,
TEXTURETYPE_FLAT
};
......@@ -100,8 +99,7 @@ void R_SetFlatVars(size_t length);
// Returns the texture number for the texture name.
INT32 R_TextureNumForName(const char *name);
INT32 R_CheckTextureNumForName(const char *name);
INT32 R_CheckFlatNumForName(const char *name);
INT32 R_CheckTextureNumForName(const char *name, UINT8 type);
// Returns the texture name for the texture number (in case you ever needed it)
const char *R_CheckTextureNameForNum(INT32 num);
......
......@@ -968,7 +968,9 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans
if (color != SKINCOLOR_NONE)
{
// New colormap stuff for skins Tails 06-07-2002
if (mobj->colorized)
if ((mobj->state-states == S_METALSONIC_DASH || mobj->state-states == S_METALSONIC_BOUNCE) && (((leveltime/2) & 1))) // Metal boss doing attack
skinnum = TC_DASHMODE;
else if (mobj->colorized)
skinnum = TC_RAINBOW;
else if (mobj->player && mobj->player->dashmode >= DASHMODE_THRESHOLD
&& (mobj->player->charflags & SF_DASHMODE)
......
......@@ -82,7 +82,7 @@ static void Captioning_OnChange(void)
{
S_ResetCaptions();
if (cv_closedcaptioning.value)
S_StartSound(NULL, sfx_menu1);
S_StartSoundFromEverywhere(sfx_menu1);
}
consvar_t cv_closedcaptioning = CVAR_INIT ("closedcaptioning", "Off", CV_SAVE|CV_CALL, CV_OnOff, Captioning_OnChange);
......@@ -516,14 +516,17 @@ void S_StartCaption(sfxenum_t sfx_id, INT32 cnum, UINT16 lifespan)
closedcaptions[set].b = 3; // bob
}
void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
void S_StartSoundAtVolume(void *origin_p, sfxenum_t sfx_id, INT32 volume, soundorigin_t soundorigin)
{
const INT32 initial_volume = volume;
INT32 sep, pitch, priority, cnum;
const sfxenum_t actual_id = sfx_id;
sfxinfo_t *sfx;
const mobj_t *origin = (const mobj_t *)origin_p;
mobj_t *origin = NULL;
if (soundorigin == SOUNDORIGIN_MOBJ)
origin = (mobj_t *)origin_p;
else if (soundorigin == SOUNDORIGIN_SECTOR)
origin = (mobj_t *)&((sector_t *)origin_p)->soundorg;
listener_t listener = {0,0,0,0};
listener_t listener2 = {0,0,0,0};
......@@ -538,6 +541,71 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
if (sfx_id == sfx_None)
return;
if (mariomode) // Sounds change in Mario mode!
{
switch (sfx_id)
{
// case sfx_altow1:
// case sfx_altow2:
// case sfx_altow3:
// case sfx_altow4:
// sfx_id = sfx_mario8;
// break;
case sfx_thok:
case sfx_wepfir:
sfx_id = sfx_mario7;
break;
case sfx_pop:
sfx_id = sfx_mario5;
break;
case sfx_jump:
sfx_id = sfx_mario6;
break;
case sfx_shield:
case sfx_wirlsg:
case sfx_forcsg:
case sfx_elemsg:
case sfx_armasg:
case sfx_attrsg:
case sfx_s3k3e:
case sfx_s3k3f:
case sfx_s3k41:
sfx_id = sfx_mario3;
break;
case sfx_itemup:
sfx_id = sfx_mario4;
break;
// case sfx_tink:
// sfx_id = sfx_mario1;
// break;
// case sfx_cgot:
// sfx_id = sfx_mario9;
// break;
// case sfx_lose:
// sfx_id = sfx_mario2;
// break;
default:
break;
}
}
if (maptol & TOL_XMAS) // Some sounds change for xmas
{
switch (sfx_id)
{
case sfx_ideya:
case sfx_nbmper:
case sfx_ncitem:
case sfx_ngdone:
++sfx_id;
default:
break;
}
}
const sfxenum_t actual_id = sfx_id =
LUA_HookSoundPlay(sfx_id, origin, soundorigin);
if (players[displayplayer].awayviewtics)
listenmobj = players[displayplayer].awayviewmobj;
......@@ -720,79 +788,48 @@ dontplay:
channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum);
}
void S_StartSound(const void *origin, sfxenum_t sfx_id)
void S_StartSoundFromEverywhereVol(sfxenum_t sfx_id, INT32 volume)
{
if (S_SoundDisabled())
return;
S_StartSoundAtVolume(NULL, sfx_id, volume, SOUNDORIGIN_EVERYWHERE);
}
if (mariomode) // Sounds change in Mario mode!
{
switch (sfx_id)
void S_StartSoundFromMobjVol(mobj_t* origin, sfxenum_t sfx_id, INT32 volume)
{
// case sfx_altow1:
// case sfx_altow2:
// case sfx_altow3:
// case sfx_altow4:
// sfx_id = sfx_mario8;
// break;
case sfx_thok:
case sfx_wepfir:
sfx_id = sfx_mario7;
break;
case sfx_pop:
sfx_id = sfx_mario5;
break;
case sfx_jump:
sfx_id = sfx_mario6;
break;
case sfx_shield:
case sfx_wirlsg:
case sfx_forcsg:
case sfx_elemsg:
case sfx_armasg:
case sfx_attrsg:
case sfx_s3k3e:
case sfx_s3k3f:
case sfx_s3k41:
sfx_id = sfx_mario3;
break;
case sfx_itemup:
sfx_id = sfx_mario4;
break;
// case sfx_tink:
// sfx_id = sfx_mario1;
// break;
// case sfx_cgot:
// sfx_id = sfx_mario9;
// break;
// case sfx_lose:
// sfx_id = sfx_mario2;
// break;
default:
break;
S_StartSoundAtVolume(origin, sfx_id, volume, SOUNDORIGIN_MOBJ);
}
}
if (maptol & TOL_XMAS) // Some sounds change for xmas
{
switch (sfx_id)
void S_StartSoundFromSectorVol(sector_t* origin, sfxenum_t sfx_id, INT32 volume)
{
case sfx_ideya:
case sfx_nbmper:
case sfx_ncitem:
case sfx_ngdone:
++sfx_id;
default:
break;
}
S_StartSoundAtVolume(origin, sfx_id, volume, SOUNDORIGIN_SECTOR);
}
void S_StartSound(void *origin, sfxenum_t sfx_id, soundorigin_t soundorigin)
{
if (S_SoundDisabled())
return;
// the volume is handled 8 bits
#ifdef HW3SOUND
if (hws_mode != HWS_DEFAULT_MODE)
HW3S_StartSound(origin, sfx_id);
else
#endif
S_StartSoundAtVolume(origin, sfx_id, 255);
S_StartSoundAtVolume(origin, sfx_id, 255, soundorigin);
}
void S_StartSoundFromEverywhere(sfxenum_t sfx_id)
{
S_StartSound(NULL, sfx_id, SOUNDORIGIN_EVERYWHERE);
}
void S_StartSoundFromMobj(mobj_t* origin, sfxenum_t sfx_id)
{
S_StartSound(origin, sfx_id, SOUNDORIGIN_MOBJ);
}
void S_StartSoundFromSector(sector_t* origin, sfxenum_t sfx_id)
{
S_StartSound(origin, sfx_id, SOUNDORIGIN_SECTOR);
}
void S_StopSound(void *origin)
......@@ -1308,7 +1345,7 @@ void S_StartSoundName(void *mo, const char *soundname)
newsounds[i] = soundnum;
}
S_StartSound(mo, soundnum);
S_StartSoundFromMobj(mo, soundnum);
}
//
......@@ -1801,6 +1838,27 @@ UINT32 S_GetMusicLength(void)
return I_GetSongLength();
}
//
// S_MusicInfo
//
// Returns metadata about supplied music
// If name is NULL, returns the currently playing music (if any)
//
musicdef_t *S_MusicInfo(const char *name)
{
if (!name)
name = music_name;
musicdef_t *def;
for (def = musicdefstart; def; def = def->next)
{
if (strcasecmp(def->name, name) == 0)
return def;
}
return NULL;
}
boolean S_SetMusicLoopPoint(UINT32 looppoint)
{
return I_SetSongLoopPoint(looppoint);
......@@ -2539,7 +2597,7 @@ void GameSounds_OnChange(void)
sound_disabled = false;
I_StartupSound(); // will return early if initialised
S_InitSfxChannels(cv_soundvolume.value);
S_StartSound(NULL, sfx_strpst);
S_StartSoundFromEverywhere(sfx_strpst);
}
else
{
......
......@@ -19,6 +19,8 @@
#include "m_fixed.h"
#include "command.h"
#include "tables.h" // angle_t
#include "r_defs.h" // S_StartSoundFromSector
#include "p_mobj.h" // S_StartSoundFromMobj
#ifdef HAVE_OPENMPT
#include "libopenmpt/libopenmpt.h"
......@@ -74,6 +76,14 @@ typedef enum
SF_X2AWAYSOUND = 64, // Hear it from 2x the distance away
} soundflags_t;
typedef enum
{
SOUNDORIGIN_EVERYWHERE = -1, //Null
SOUNDORIGIN_MOBJ = 0, //Mobj
SOUNDORIGIN_SECTOR = 1, //Sector
} soundorigin_t;
typedef struct {
fixed_t x, y, z;
angle_t angle;
......@@ -142,10 +152,16 @@ boolean S_SoundDisabled(void);
//
// Start sound for thing at <origin> using <sound_id> from sounds.h
//
void S_StartSound(const void *origin, sfxenum_t sound_id);
void S_StartSound(void *origin, sfxenum_t sound_id, soundorigin_t soundorigin);
void S_StartSoundFromEverywhere(sfxenum_t sound_id);
void S_StartSoundFromMobj(mobj_t *origin, sfxenum_t sound_id);
void S_StartSoundFromSector(sector_t *origin, sfxenum_t sound_id);
// Will start a sound at a given volume.
void S_StartSoundAtVolume(const void *origin, sfxenum_t sound_id, INT32 volume);
void S_StartSoundAtVolume(void *origin, sfxenum_t sound_id, INT32 volume, soundorigin_t soundorigin);
void S_StartSoundFromEverywhereVol(sfxenum_t sfx_id, INT32 volume);
void S_StartSoundFromMobjVol(mobj_t* origin, sfxenum_t sfx_id, INT32 volume);
void S_StartSoundFromSectorVol(sector_t* origin, sfxenum_t sfx_id, INT32 volume);
// Stop sound for thing at <origin>
void S_StopSound(void *origin);
......@@ -220,6 +236,9 @@ boolean S_PrepareSoundTest(void);
// Get Length of Music
UINT32 S_GetMusicLength(void);
// Get MUSICDEF of Music
musicdef_t *S_MusicInfo(const char *name);
// Set LoopPoint of Music
boolean S_SetMusicLoopPoint(UINT32 looppoint);
......@@ -325,8 +344,8 @@ void S_StopSoundByID(void *origin, sfxenum_t sfx_id);
void S_StopSoundByNum(sfxenum_t sfxnum);
#ifndef HW3SOUND
#define S_StartAttackSound S_StartSound
#define S_StartScreamSound S_StartSound
#define S_StartAttackSound S_StartSoundFromMobj
#define S_StartScreamSound S_StartSoundFromMobj
#endif
#endif
......@@ -124,6 +124,7 @@ void SCR_SetDrawFuncs(void)
spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8;
spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8;
spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_8;
spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8;
......@@ -146,6 +147,7 @@ void SCR_SetDrawFuncs(void)
spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8;
......@@ -493,11 +495,9 @@ void SCR_ClosedCaptions(void)
basey -= 42;
else if (splitscreen)
basey -= 8;
else if ((modeattacking == ATTACKING_NIGHTS)
|| (!(maptol & TOL_NIGHTS)
&& LUA_HudEnabled(hud_powerups)
else if (LUA_HudEnabled(hud_powerups)
&& ((cv_powerupdisplay.value == 2) // "Always"
|| (cv_powerupdisplay.value == 1 && !camera.chase)))) // "First-person only"
|| (cv_powerupdisplay.value == 1 && !camera.chase))) // "First-person only"
basey -= 16;
}
......