Compare commits

..
Author SHA1 Message Date
alufolie91 9936f9c740 have Z_IsMobjValid2 print an error in console
if mobj pointer is invalid
the callee should handle the behavior
2026-10-02 18:23:29 +02:00
alufolie91 bee5c8e5ed add code to check for mobj pointer validity
as we use the pool allocator we may check if a mobj points into the address range of the level pool specific to mobj allocations (g_level_large_pool)
this may help in debugging stuff without the need to run things like ASAN or valgrind
2026-10-02 18:23:26 +02:00
40 changed files with 691 additions and 832 deletions

No files matched your search

-2
View File
@@ -246,8 +246,6 @@ set(SRB2_CONFIG_ASAN OFF CACHE BOOL
"Compile with AddressSanitizer (libasan).")
set(SRB2_CONFIG_UBSAN OFF CACHE BOOL
"Compile with UndefinedBehaviorSanitizer (libubsan).")
set(SRB2_CONFIG_TSAN OFF CACHE BOOL
"Compile with ThreadSanitizer (libtsan).")
set(SRB2_CONFIG_MUMBLE ON CACHE BOOL
"Enable Mumble support")
+5 -18
View File
@@ -75,7 +75,6 @@
# PROFILEMODE=1 - Enable performance profiling (gprof).
# USEASAN=1 - Enable building with Address Sanitizer.
# USEUBSAN=1 - Enable building with Undefined Behavior Sanitizer.
# USETSAN=1 - Enable building with Thread Sanitizer.
# NOLIBBACKTRACE=1 - Disable using Libbacktrace for crashlog traces.
#
# General flags for building:
@@ -262,35 +261,23 @@ debug_opts=-D_DEBUG
else # build a normal optimized version
debug_opts=-DNDEBUG
opts+=-O3
ifndef NOLTO
# compile with LTO
opts+=-flto=auto
libs+=-flto=auto
endif
endif
ifdef USEASAN
# compile with asan
opts+=-O1 -fsanitize=address -fno-omit-frame-pointer -fno-common
libs+=-fsanitize=address
NOLTO=1
endif
ifdef USEUBSAN
# compile with ubsan
opts+=-O1 -fsanitize=undefined -fno-omit-frame-pointer
libs+=-fsanitize=undefined
NOLTO=1
endif
ifdef USETSAN
# compile with tsan
opts+=-O1 -fsanitize=thread -fno-omit-frame-pointer
libs+=-fsanitize=thread
NOLTO=1
endif
ifndef DEBUGMODE
ifndef NOLTO
# compile with LTO
opts+=-flto=auto
libs+=-flto=auto
endif
endif
ifdef USEJEMALLOC
-1
View File
@@ -1739,7 +1739,6 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
// send the value of the variable
UINT8 buf[128];
UINT8 *p = buf;
if (!(server || (IsPlayerAdmin(consoleplayer))))
{
CONS_Alert(CONS_NOTICE, "Only the server or admin can change: %s %s\n", var->name, var->string);
+24
View File
@@ -149,6 +149,30 @@ void PoolAllocator::release()
allocated_blocks_ = 0;
}
bool PoolAllocator::ptrcheck(const void* p) const
{
const uintptr_t paddr = reinterpret_cast<uintptr_t>(p);
ChunkFooter* next = nullptr;
for (ChunkFooter* chunk = first_chunk_; chunk != nullptr; chunk = next)
{
const uintptr_t blockstart = reinterpret_cast<uintptr_t>(chunk->start);
const uintptr_t blockend = blockstart + blocks_ * block_size_;
//CONS_Printf("mobj ptr %lu, block start %lu end %lu\n", paddr, blockstart, blockend);
if (paddr >= blockstart && paddr < blockend)
{
return true;
}
next = chunk->next;
}
return false;
}
static LinearMemory g_frame_memory {4 * 1024 * 1024};
void* Z_Frame_Alloc(size_t size)
+1
View File
@@ -65,6 +65,7 @@ public:
constexpr size_t allocated_bytes() const noexcept { return allocated_blocks_ * block_size_; };
void release();
bool ptrcheck(const void* p) const;
};
} // namespace srb2
+2 -8
View File
@@ -1149,19 +1149,13 @@ static void D_FindAddonsToAutoload(void)
// ok so theres still issues with players adding stuff to autoload by accident
// sometimes this stuff contains maps
// you can probably imagine how that goes in a netgame....
int retmap = W_CheckAutoLoadContainsMap(wadsToAutoload);
if (retmap == -1)
{
CONS_Alert(CONS_WARNING, "Autoload: file %s was not found or not valid.\n", wadsToAutoload);
continue;
}
if (retmap > 0)
if (W_CheckAutoLoadContainsMap(wadsToAutoload))
{
CONS_Alert(CONS_WARNING, "Autoload: file %s contains map data, this WILL cause crashes and desynchs! skipping...\n", wadsToAutoload);
continue;
}
if (!postload && W_CheckPostLoadList(wadsToAutoload) > 0)
if (!postload && W_CheckPostLoadList(wadsToAutoload))
{
CONS_Printf("Autoload: forcing postload for file %s\n", wadsToAutoload);
postload = true;
+3 -12
View File
@@ -361,17 +361,11 @@ typedef struct squishdance_s
{
tic_t countdown; // hold "custom 3" for 2 seconds to engange le dance
tic_t time;
fixed_t work;
fixed_t ang;
fixed_t bounce; // hehe squishy
} squishdance_t;
typedef struct salty_s
{
bool ready;
bool tapping;
fixed_t zoffset;
fixed_t momz;
bool jump;
} salty_t;
// ========================================================================
// PLAYER STRUCTURE
// ========================================================================
@@ -567,9 +561,6 @@ typedef struct player_s
fixed_t spinoutrot; // When a player spins out, this value increments modulus 360.
// saltyhop! hardcode edition
salty_t salty;
squishdance_t squishdance;
fixed_t fovadd; // adjust FOV for hw rendering
+3 -8
View File
@@ -119,25 +119,20 @@ target_compile_definitions(SRB2SDL2 PRIVATE
-DHAVE_THREADS
)
if(SRB2_CONFIG_LTO AND NOT SRB2_CONFIG_DEBUGMODE AND NOT SRB2_CONFIG_ASAN AND NOT SRB2_CONFIG_UBSAN AND NOT SRB2_CONFIG_TSAN)
if(SRB2_CONFIG_LTO AND NOT SRB2_CONFIG_DEBUGMODE)
set_property(TARGET SRB2SDL2 PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
if(SRB2_CONFIG_ASAN)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=address -fno-omit-frame-pointer -fno-common)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=address)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=address)
endif()
if(SRB2_CONFIG_UBSAN)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=undefined -fno-omit-frame-pointer)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
endif()
if(SRB2_CONFIG_TSAN)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=thread -fno-omit-frame-pointer)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=thread)
endif()
## strip debug symbols into separate file when using gcc
# if(CMAKE_COMPILER_IS_GNUCC)
# if(${CMAKE_BUILD_TYPE} MATCHES Debug)
+1 -4
View File
@@ -474,7 +474,6 @@ void DRPC_UpdatePresence(void)
char charname[11+SKINNAMESIZE+1];
boolean joinSecretSet = false;
char *clientJoinSecret = NULL;
DiscordRichPresence discordPresence;
memset(&discordPresence, 0, sizeof(discordPresence));
@@ -531,8 +530,7 @@ void DRPC_UpdatePresence(void)
// Grab the host's IP for joining.
if ((join = DRPC_GetServerIP()) != NULL)
{
clientJoinSecret = DRPC_XORIPString(join);
discordPresence.joinSecret = clientJoinSecret;
discordPresence.joinSecret = DRPC_XORIPString(join);
joinSecretSet = true;
}
}
@@ -714,7 +712,6 @@ void DRPC_UpdatePresence(void)
}
Discord_UpdatePresence(&discordPresence);
free(clientJoinSecret);
}
#endif // HAVE_DISCORDRPC
+58 -27
View File
@@ -63,6 +63,7 @@
// for replay dates
#include <time.h>
#include <locale.h>
// menu demo things
UINT32 demoDelayTime = 15*TICRATE;
@@ -2386,9 +2387,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
#if defined (_WIN32)
// return the file creation time
// useful for demos that were renamed
// windows only, as file creation times are
// very unreliable (or non existant depending on fs) on linux
static time_t G_GetCreationTime(char *filepath)
static long G_GetCreationTime(char *filepath)
{
struct stat fileinfo;
@@ -2399,24 +2398,35 @@ static time_t G_GetCreationTime(char *filepath)
}
#endif
static char *G_GetDemoDate(menudemo_t *pdemo, const char *dateformat)
static char *G_GetDemoDate(menudemo_t *pdemo)
{
char *endPos = NULL;
char *datetime;
static char datetime[11];
time_t file_time = 0;
struct tm tm_buf;
const char *format = NULL;
struct tm *tm_buf = NULL;
CLEANUP(pfree) char *filename = NULL;
// get le filepath
filename = strdup(pdemo->filepath);
if (!filename)
{
#if defined (_WIN32)
// if we cant get a filename try just getting the file creation time
file_time = G_GetCreationTime(pdemo->filepath);
goto skipfilenametime;
#else
return NULL;
#endif
}
// get the actual filename Zzz...
nameonly(filename);
// the first 10 characters of a replay name is a unix timestamp
// the first 10 characters of a replay name usually is a unix timestamp
// not long enough to contain a valid timestamp
if (strlen(filename) < 10)
{
#if defined (_WIN32)
@@ -2448,49 +2458,67 @@ static char *G_GetDemoDate(menudemo_t *pdemo, const char *dateformat)
#endif
}
// then throw it into localtime to get an actual human readable format lmao
#if defined(_WIN32)
#if defined (_WIN32)
skipfilenametime:
if ((localtime_s(&tm_buf, &file_time) != 0) ||
(tm_buf.tm_year <= 110)) // cant believe we ended up in 1970
#endif
// then throw it into localtime to get an actual human readable format lmao
tm_buf = localtime(&file_time);
// cant believe we ended up in 1970
if (tm_buf == NULL || tm_buf->tm_year <= 110)
{
#if defined (_WIN32)
// uh ohh, we got an invalid time
// try one more time getting the creation time
file_time = G_GetCreationTime(pdemo->filepath);
tm_buf = localtime(&file_time);
if ((localtime_s(&tm_buf, &file_time) != 0) ||
(tm_buf.tm_year <= 110))
if (tm_buf == NULL || tm_buf->tm_year <= 110)
return NULL;
}
goto gotcreationtime;
#else
if ((localtime_r(&file_time, &tm_buf) == NULL) ||
(tm_buf.tm_year <= 110)) // cant believe we ended up in 1970
return NULL;
#endif
}
datetime = malloc(sizeof(pdemo->date)); // mallocma balls
#if defined (_WIN32)
gotcreationtime:
#endif
// no mallocma balls... :c
if (!datetime)
return NULL;
// US ppl are special (:
if (cv_demodateformat.value == 2)
format = "%m.%d.%Y";
else if (cv_demodateformat.value == 1)
format = "%d.%m.%Y";
else
{
const char *locale = setlocale(LC_TIME, NULL);
if (strftime(datetime, sizeof(pdemo->date), dateformat, &tm_buf) == 0)
if (locale == NULL)
format = "%d.%m.%Y"; // fallback to non US format
else if (strstr(locale, "en_US"))
format = "%m.%d.%Y";
else
format = "%d.%m.%Y";
}
if (strftime(datetime, sizeof(datetime), format, tm_buf) == 0)
{
free(datetime);
return NULL;
}
return datetime;
}
void G_LoadDemoTitle(menudemo_t *pdemo, const char *dateformat)
void G_LoadDemoTitle(menudemo_t *pdemo)
{
UINT8 infobuffer[96], *info_p;
UINT16 pdemoversion;
char *demodate = NULL;
size_t count;
memset(pdemo->date, 0, sizeof(pdemo->date));
FILE *handle = fopen(pdemo->filepath, "rb");
if (!handle)
@@ -2518,6 +2546,8 @@ void G_LoadDemoTitle(menudemo_t *pdemo, const char *dateformat)
pdemoversion = READUINT16(info_p);
memset(pdemo->date, 0, sizeof(pdemo->date));
switch (pdemoversion)
{
case DEMOVERSION: // latest always supported
@@ -2525,12 +2555,13 @@ void G_LoadDemoTitle(menudemo_t *pdemo, const char *dateformat)
memcpy(pdemo->title, info_p, 64);
// demo date
char *demodate = G_GetDemoDate(pdemo, dateformat);
demodate = G_GetDemoDate(pdemo);
if (demodate)
{
strlcpy(pdemo->date, demodate, sizeof(pdemo->date));
free(demodate);
}
break;
#ifdef DEMO_COMPAT_100
case 0x0001:
+1 -1
View File
@@ -98,7 +98,7 @@ void G_SetDemoTime(UINT32 ptime, UINT32 plap);
UINT8 G_CmpDemoTime(char *oldname, char *newname);
void G_LoadDemoInfo(menudemo_t *pdemo);
void G_LoadDemoTitle(menudemo_t *pdemo, const char *dateformat); // For use in replay search feature
void G_LoadDemoTitle(menudemo_t *pdemo); // For use in replay search feature
void G_DeferedPlayDemo(const char *demo);
typedef enum
+16 -100
View File
@@ -96,7 +96,7 @@ static void HWR_FreePoly(poly_t *poly)
// divfrac = how far along partline vector is crossing pt
static boolean fracdivline(fdivline_t *partline, polyvertex_t *v1, polyvertex_t *v2)
{
double frac;
double frac1, frac2;
double num; // numerator
double den; // denominator
double v1x, v1y, v1dx, v1dy; // polygon side vector, v1->v2
@@ -122,23 +122,24 @@ static boolean fracdivline(fdivline_t *partline, polyvertex_t *v1, polyvertex_t
// first check the frac along the polygon segment,
// (do not accept hit with the extensions)
num = (v3x - v1x)*v3dy + (v1y - v3y)*v3dx;
frac = num / den;
frac1 = num / den;
// 0= cross at v1, 1.0= cross at v2
if (frac < 0.0 || frac > 1.0) // double
if (frac1 < 0.0 || frac1 > 1.0) // double
return false; // not within the polygon side
// now get the frac along the BSP line
// which is useful to determine what is left, what is right
num = (v3x - v1x)*v1dy + (v1y - v3y)*v1dx;
frac2 = num / den;
partline->divfrac = num / den; // how far along partline vector
partline->divfrac = frac2; // how far along partline vector
// [WDJ] find the interception point along the segment.
// It should be slightly more accurate because it is always closer to the
// crossing point than arbitrary positions on the partition line.
partline->divpt.x = v1x + v1dx*frac;
partline->divpt.y = v1y + v1dy*frac;
partline->divpt.x = v1x + v1dx*frac1;
partline->divpt.y = v1y + v1dy*frac1;
return true;
}
@@ -160,71 +161,6 @@ static boolean SameVertex(polyvertex_t *p1, polyvertex_t *p2)
return true;
}
// Adapted from function in prboom.
// Point is to rightside of divline when result > 0,
// but result is multiplied by length of divline.
// Returns near 0, when point is on, or nearly on, the divline.
static inline double point_rightside(fdivline_t *dl, polyvertex_t *v4)
{
// Cross product of dl and vector dl->(x,y) to v4,
// is > 0 when v4 is to right side of divline.
// Viewed along divline from vertex, looking towards positive dx,dy.
// If divline is rotated until dy>0 and dx = 0, then true when rotated
// vertex position is to the right of the divline (v4->x > dl->x).
return ((((double)(v4->x) - (double)(dl->x)) * (double)(dl->dy))
- (((double)(v4->y) - (double)(dl->y)) * (double)(dl->dx)));
}
// [WDJ] The front and back MUST match the BSP determination, else it will assign
// this poly to the wrong sector.
// May have 1 point on the line, and other points might be very close to the line.
// Can only trust a test of a point that is NOT on the line.
// Using a tstdist = 0.5f worked, but it might break on very small poly.
// Avactor.wad had polys with d = 9.09, 5552, 1.64, 1011, 14252, 0.0136, 0.00634, 14655, 3,
// -0.3044, 7, 1.53, etc..,
// and one poly with d = -0.023 with the rest of the points d > 0.
// One 14 point poly with divline len=8, had to test 9 points to find d = 36.
// Typical: divline len=70 d=6828, divline len=1.0 d=35, divline len=1.414 d=5.
// The result of point_rightside is proportional to the length of divline.
// The divline length can be from 1.414 to 14000.
static void UnsplitPoly(fdivline_t *dlnp, poly_t *poly,
poly_t **frontpoly, poly_t **backpoly)
{
int32_t i;
double d;
const double tstd = hypot((double)dlnp->dx, (double)dlnp->dy) / 2.0;
double sumd = 0; // accumulated left or rightness.
for (i = 0; i < poly->numpts; i++)
{
// Look for a point that is obviously to the left or right.
d = point_rightside(dlnp, &poly->pts[i]); // d > 0 is right
sumd += d;
if (d > tstd)
goto poly_rightside;
if (d < -tstd)
goto poly_leftside;
}
// Did not find an obvious left or right point, then
if (sumd < 0)
goto poly_leftside;
poly_rightside:
// poly is to rightside of divline.
*frontpoly = poly;
*backpoly = NULL;
return;
poly_leftside:
// poly is to leftside of divline.
*frontpoly = NULL;
*backpoly = poly;
return;
}
// split a _CONVEX_ polygon in two convex polygons
// outputs:
// frontpoly : polygon on right side of bsp line
@@ -327,7 +263,10 @@ static void SplitPoly (fdivline_t *dlnp, // splitting parametric line
// linedefs where each side point the same sector, that is:
// the deep water effect with the original Doom
UnsplitPoly(dlnp, poly, frontpoly, backpoly);
//TODO: make sure front poly is to front of partition line?
*frontpoly = poly;
*backpoly = NULL;
return;
}
@@ -335,14 +274,16 @@ static void SplitPoly (fdivline_t *dlnp, // splitting parametric line
if (pe < 0)
{
//I_Error("SplitPoly: only one point for split line (%d %d)", ps, pe);
UnsplitPoly(dlnp, poly, frontpoly, backpoly);
*frontpoly = poly;
*backpoly = NULL;
return;
}
if (pe <= ps)
{
//I_Error("SplitPoly: invalid splitting line (%d %d)", ps, pe);
UnsplitPoly(dlnp, poly, frontpoly, backpoly);
*frontpoly = poly;
*backpoly = NULL;
return;
}
@@ -447,10 +388,6 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 segcount, poly_t *poly)
vertex_t *v1, *v2;
fdivline_t cutseg; // x, y, dx, dy as start of node_t struct
// empty poly? just save us some time then
if (poly->numpts <= 0)
return frontpoly;
// for each seg of the subsector
for (; segcount--; lseg++)
{
@@ -552,23 +489,6 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 segcount, poly_t *poly)
// need 2 points
if (pe >= 0)
{
// Cuts that miss the polygon.
if (ps_frac < 0.0 && cutseg.divfrac < 0.0)
continue;
if (ps_frac > 1.0 && cutseg.divfrac > 1.0)
continue;
#define FRAC_EP 0.01f
// Reject cuts that could make the polygon non-convex.
// Cannot make normal cut, ps_frac end is loose.
if ((ps_frac < (0.0 - FRAC_EP)) || (ps_frac > (1.0f + FRAC_EP)))
continue;
// Cannot make normal cut, cutseg.divfrac end is loose.
if ((cutseg.divfrac < (0.0 - FRAC_EP)) || (cutseg.divfrac > (1.0f + FRAC_EP)))
continue;
#undef FRAC_EP
// generate FRONT poly
frontpoly = HWR_AllocPoly(poly_num_pts);
@@ -760,11 +680,7 @@ static void WalkBSPNode(INT32 bspnum, poly_t *poly, UINT16 *leafnode, fixed_t *b
memcpy(bbox, bsp->bbox[0], 4*sizeof (fixed_t));
}
else
{
// [WDJ] Having no front poly is as likely as no back poly, since
// logic in Split Poly was changed to check poly direction.
// I_Error("HWR_WalkBSPNode: no front poly, bspnum= %d\n", bspnum);
}
I_Error("WalkBSPNode: no front poly?");
// Recursively divide back space.
if (backpoly)
+40 -19
View File
@@ -614,12 +614,24 @@ void HWR_FreeMapTextures(void)
gl_numtextures = 0;
}
#define NAME flatcheck
#define KEY_TY UINT32
#define HASH_FN vt_hash_integer
#define CMPR_FN vt_cmpr_integer
#include "../verstable.h"
static void HWR_PrecacheLevelFlats(void)
{
// lookup for flats that may´ve been already loaded
flatcheck flatpresent;
size_t i;
#if 0
size_t j;
#endif
INT32 k;
// FIXME: this needs to account for FOFs to properly work
// this kinda messes up encore remapping behavior at times
// so just disable it for now ig
#ifdef GLENCORE
if (encoremap)
{
@@ -627,6 +639,9 @@ static void HWR_PrecacheLevelFlats(void)
}
#endif
flatcheck_init(&flatpresent);
flatcheck_reserve(&flatpresent, numlevelflats);
// special case for encore
#if 0
#ifdef GLENCORE
@@ -635,7 +650,6 @@ static void HWR_PrecacheLevelFlats(void)
// go through all sectors to determine if it should be remapped for encore
for (i = 0; i < numsectors; i++)
{
size_t j;
sector_t *sec = &sectors[i];
// gotta check sector floor and ceiling
@@ -678,7 +692,11 @@ static void HWR_PrecacheLevelFlats(void)
{
const levelflat_t *levelflat = &levelflats[i];
HWR_GetFlat(levelflat->lumpnum, false);
if (flatcheck_is_end(flatcheck_get(&flatpresent, levelflat->lumpnum)))
{
HWR_GetFlat(levelflat->lumpnum, false);
flatcheck_insert(&flatpresent, levelflat->lumpnum);
}
if (levelflat->speed) // is it an animated flat ?
{
@@ -686,11 +704,17 @@ static void HWR_PrecacheLevelFlats(void)
for (k = 0; k < levelflat->numpics; k++)
{
lumpnum_t lump = levelflat->baselumpnum + k;
HWR_GetFlat(lump, false);
if (flatcheck_is_end(flatcheck_get(&flatpresent, lump)))
{
HWR_GetFlat(lump, false);
flatcheck_insert(&flatpresent, lump);
}
}
}
}
}
flatcheck_cleanup(&flatpresent);
}
static void HWR_PrecacheLevelTextures(void)
@@ -714,7 +738,7 @@ static void HWR_PrecacheLevelTextures(void)
{
const line_t *line = &lines[i];
#ifdef GLENCORE
const boolean noencoremap = (encoremap && (line->flags & ML_TFERLINE));
const int noencoremap = ((encoremap && (line->flags & ML_TFERLINE)) ? 2 : 1);
#endif
// two sides
for (j = 0; j < 2; j++)
@@ -731,27 +755,25 @@ static void HWR_PrecacheLevelTextures(void)
{
const INT32 texnum = sidetex[f];
if (texnum <= 0 || (unsigned)texnum >= gl_numtextures)
if (texnum < 0 || texnum >= (signed)gl_numtextures)
continue;
if (!(texturepresent[texnum] & 1))
{
texturepresent[texnum] |= 1;
HWR_GetTexture(texnum, false);
}
if (texturepresent[texnum])
continue;
#ifdef GLENCORE
if (noencoremap
&& !(texturepresent[texnum] & 2))
{
texturepresent[texnum] |= 2;
texturepresent[texnum] = 1|noencoremap;
#else
texturepresent[texnum] = 1;
#endif
HWR_GetTexture(texnum, false);
#ifdef GLENCORE
if (noencoremap & 2)
HWR_GetTexture(texnum, true);
}
#endif
}
}
}
// check for animated textures
for (anim = anims; anim < lastanim; anim++)
{
if (!anim->istexture)
@@ -770,7 +792,6 @@ static void HWR_PrecacheLevelTextures(void)
{
HWR_GetTexture(animtexnum, false);
}
#ifdef GLENCORE
if (texpresent & 2)
{
@@ -892,7 +913,7 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean noencore)
GLMapTexture_t *gltex;
GLMipmap_t *glMipmap;
if (tex < 0 || (unsigned)tex >= gl_numtextures)
if (tex < 0 || tex >= (signed)gl_numtextures)
{
#ifdef PARANOIA
I_Error("HWR_GetTexture: Invalid texture ID %d", tex);
+59 -89
View File
@@ -255,7 +255,6 @@ static void CV_screentextures_OnChange(void)
#endif
intermissionbginit = false;
}
GL_SetSpecialState(HWD_SET_SCREEN_TEXTURES, cv_glscreentextures.value);
M_UpdateOGLMenu();
}
@@ -264,11 +263,12 @@ static void CV_screentextures_OnChange(void)
static void CV_glframebuffer_OnChange(void)
{
ONLY_IF_GL_LOADED
// screen FBO needs screen textures currently
if (cv_glframebuffer.value != 0 && ((cv_glscreentextures.value != 2) || !supportFBO))
CV_StealthSetValue(&cv_glframebuffer, 0); // dont recursively call this lul
if ((cv_glframebuffer.value != 0 && cv_glscreentextures.value != 2)
|| (!supportFBO && cv_glframebuffer.value != 0)) // screen FBO needs screen textures
CV_SetValue(&cv_glframebuffer, 0);
I_CheckDownSampleState(true);
I_DownSample();
RefreshOGLSDLSurface();
M_UpdateOGLMenu();
intermissionbginit = false;
}
@@ -610,7 +610,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
fflatsize = 1024.0f;
flatflag = 1023;
break;
case 262144: // 512x512 lump
case 262144:// 512x512 lump
fflatsize = 512.0f;
flatflag = 511;
break;
@@ -721,7 +721,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false);
if (gl_maphashorizonlines && subsector && !FOFsector && cv_glhorizonlines.value)
if (gl_maphashorizonlines && subsector && cv_glhorizonlines.value)
{
// Horizon lines
FOutVector horizonpts[6];
@@ -742,6 +742,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
line_t* ld = line->linedef;
// this check sucks and is a hotspot lel
if (LIKELY(ld->special != HORIZONSPECIAL))
continue;
@@ -1239,44 +1240,46 @@ static inline boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf)
pSurf->PolyColor.s.alpha = 0xFF;
// check if linedef alpha is within range
const boolean linealpha = (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT);
// set alpha for transparent walls
switch (gl_linedef->special)
if (LIKELY(!gl_curline->polyseg))
{
// Translucent linedef types
case 102:
case 121 ... 125:
case 141 ... 145:
case 174:
case 175:
case 192:
case 195:
case 221:
case 253:
case 256:
if (gl_linedef->blendmode && linealpha)
blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = PF_Translucent;
break;
default:
if (gl_linedef->blendmode)
{
if (linealpha)
// check if linedef alpha is within range
const boolean linealpha = (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT);
// set alpha for transparent walls
switch (gl_linedef->special)
{
// Translucent linedef types
case 102:
case 121 ... 125:
case 141 ... 145:
case 174:
case 175:
case 192:
case 195:
case 221:
case 253:
case 256:
if (gl_linedef->blendmode && linealpha)
blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = HWR_GetBlendModeFlag(gl_linedef->blendmode);
}
else if (linealpha)
blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = PF_Masked;
break;
blendmode = PF_Translucent;
break;
default:
if (gl_linedef->blendmode)
{
if (linealpha)
blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = HWR_GetBlendModeFlag(gl_linedef->blendmode);
}
else if (linealpha)
blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), pSurf);
else
blendmode = PF_Masked;
break;
}
}
if (gl_curline->polyseg && gl_curline->polyseg->translucency > 0)
else if (gl_curline->polyseg->translucency > 0)
{
// Polyobject translucency is shared between all of its lines
if (gl_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn
@@ -1383,8 +1386,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// two sided line
if (gl_backsector)
{
const INT32 gl_toptexture = R_GetTextureNum(gl_sidedef->toptexture);
const INT32 gl_bottomtexture = R_GetTextureNum(gl_sidedef->bottomtexture);
INT32 gl_toptexture = 0, gl_bottomtexture = 0;
fixed_t texturevpeg;
@@ -1395,7 +1397,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if (!gl_curline->polyseg) // Don't do it for polyobjects
{
// Sky Ceilings
wallVerts[2].y = wallVerts[3].y = FLOATMAX; // draw to top of map space
wallVerts[3].y = wallVerts[2].y = FLOATMAX;
auto draw_sky_walls = []
(int vert1, int vert2, fixed_t world, fixed_t worldslope, auto& wwallVerts, auto& sSurf) FUNCINLINE
@@ -1405,9 +1407,6 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
HWR_DrawSkyWall(wwallVerts, &sSurf);
};
// worldtop = front ceiling
// worldhigh = back ceiling
if (gl_frontsector->ceilingpic == skyflatnum)
{
if (gl_backsector->ceilingpic == skyflatnum)
@@ -1426,17 +1425,6 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
worldtop = worldhigh;
worldtopslope = worldhighslope;
}
else if (!gl_toptexture &&
(worldhigh <= worldtop && worldhighslope <= worldtopslope) && // Assuming ESLOPE is always on with my changes
(worldhigh != worldtop || worldhighslope != worldtopslope))
{
// Only the frontsector is sky.
// If there's no upper texture, extend the sky wall
// down to the lower of the two ceilings.
fixed_t top = std::min(worldtop, worldhigh);
fixed_t topslope = std::min(worldtopslope, worldhighslope);
draw_sky_walls(0, 1, top, topslope, wallVerts, Surf);
}
else
{
// Only the frontsector is sky, just draw a skywall from the front ceiling
@@ -1449,11 +1437,8 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
draw_sky_walls(0, 1, worldtop, worldtopslope, wallVerts, Surf);
}
// worldbottom = front floor
// worldlow = back floor
// Sky Floors
wallVerts[0].y = wallVerts[1].y = FLOATMIN; // draw to bottom of map space
wallVerts[0].y = wallVerts[1].y = FLOATMIN;
if (gl_frontsector->floorpic == skyflatnum)
{
@@ -1465,7 +1450,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if ((worldlow >= worldbottom && worldlowslope >= worldbottomslope)
&& (worldlow != worldbottom || worldlowslope != worldbottomslope)
// Removing the second line above will render more rarely visible skywalls. Example: Cave garden ceiling in Dark race
&& !(gl_bottomtexture))
&& !(gl_sidedef->bottomtexture))
{
draw_sky_walls(3, 2, worldlow, worldlowslope, wallVerts, Surf);
}
@@ -1476,25 +1461,15 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
draw_sky_walls(3, 2, worldbottom, worldbottomslope, wallVerts, Surf);
}
}
else if ((gl_backsector->floorpic == skyflatnum) && !(gl_bottomtexture))
else if ((gl_backsector->floorpic == skyflatnum) && !(gl_sidedef->bottomtexture))
{
// Only the backsector has sky, just draw a skywall from the back floor if there's no bottomtexture
draw_sky_walls(3, 2, worldlow, worldlowslope, wallVerts, Surf);
}
else if (gl_frontsector->ceilingpic == skyflatnum &&
gl_backsector->ceilingpic == skyflatnum &&
(worldlow >= worldbottom && worldlowslope >= worldbottomslope)
&& (worldlow != worldbottom || worldlowslope != worldbottomslope)
// Removing the second line above will render more rarely visible skywalls. Example: Cave garden ceiling in Dark race
&& !(gl_bottomtexture))
{
// Both ceilings are sky, but neither floor is sky.
// If there's a lower wall gap without a bottom texture,
// draw a skywall from the backsector's higher floor.
draw_sky_walls(3, 2, worldlow, worldlowslope, wallVerts, Surf);
}
}
gl_toptexture = R_GetTextureNum(gl_sidedef->toptexture);
// check TOP TEXTURE
if (gl_toptexture && (worldhighslope < worldtopslope || worldhigh < worldtop))
{
@@ -1558,6 +1533,8 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
}
gl_bottomtexture = R_GetTextureNum(gl_sidedef->bottomtexture);
// check BOTTOM TEXTURE
if (gl_bottomtexture && (worldlowslope > worldbottomslope || worldlow > worldbottom))
{
@@ -2985,7 +2962,7 @@ static void HWR_Subsector(size_t num)
}
else
{
HWR_GetFlat(flatlump, R_NoEncore(rover->master->frontsector, bottom));
HWR_GetFlat(flatlump, R_NoEncore(gl_frontsector, !bottom));
light = R_GetPlaneLight(gl_frontsector, centerHeight, underside);
HWR_RenderPlane(sub, &extrasubsectors[num], !bottom, roverheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, flatlump,
@@ -3483,12 +3460,8 @@ static inline void HWR_ApplyDispoffset(gl_vissprite_t *spr, FOutVector *wallVert
{
HWR_RotateSpritePolyToAim(spr, wallVerts, false, papersprite);
const float f_xdiff = (spr->x1 - gl_viewx);
const float f_ydiff = (spr->z1 - gl_viewy);
const float f_zdiff = (spr->gzt - gl_viewz);
const float sprdist = sqrtf((f_xdiff*f_xdiff) + (f_ydiff*f_ydiff) + (f_zdiff*f_zdiff));
const float distfact = ((2.0f * spr->dispoffset) + 20.0f) / sprdist;
const float sprdist = sqrtf((spr->x1 - gl_viewx)*(spr->x1 - gl_viewx) + (spr->z1 - gl_viewy)*(spr->z1 - gl_viewy) + (spr->gzt - gl_viewz)*(spr->gzt - gl_viewz));
const float distfact = ((2.0f*spr->dispoffset) + 20.0f) / sprdist;
for (size_t i = 0; i < 4; i++)
{
@@ -4314,10 +4287,7 @@ static void HWR_RenderDrawNodes(void)
gl_frontsector = NULL;
if (!(plane->blend & PF_NoTexture))
{
const boolean ceiling = plane->FOFSector ? !plane->isceiling : plane->isceiling; // match software!
HWR_GetFlat(plane->lumpnum, R_NoEncore(plane->FOFSector, ceiling));
}
HWR_GetFlat(plane->lumpnum, R_NoEncore(plane->FOFSector, plane->isceiling));
HWR_RenderPlane(NULL, plane->xsub, plane->isceiling, plane->fixedheight, plane->blend, plane->lightlevel,
plane->lumpnum, plane->FOFSector, plane->alpha, plane->planecolormap);
@@ -5899,7 +5869,7 @@ void HWR_Startup(void)
HWR_TogglePaletteRendering();
if (msaa)
GL_SetSpecialState(HWD_SET_MSAA, 1);
GL_SetSpecialState(HWD_SET_MSAA, a2c ? 2 : 1);
HWR_RegisterCommands();
}
@@ -5987,7 +5957,7 @@ void HWR_Shutdown(void)
GL_FlushScreenTextures();
HWR_ClearAllTextures();
#ifdef USE_FBO_OGL
GL_FBO_Disable();
GL_Framebuffer_Disable();
#endif
}
+1
View File
@@ -43,6 +43,7 @@ void HWR_Startup(void);
void HWR_Shutdown(void);
extern unsigned msaa;
extern boolean a2c;
extern FTransform atransform;
extern float gl_viewsin, gl_viewcos;
+3 -3
View File
@@ -1146,8 +1146,8 @@ void HWR_DrawMD2(gl_vissprite_t *spr)
// Look at HWR_ProjectSprite for more
{
md2_t *md2s = NULL;
int skinnum = 0;
md2_t *md2s;
int skinnum;
patch_t *gpatch, *blendgpatch;
GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL;
INT32 durs = spr->mobj->state->tics;
@@ -1221,7 +1221,7 @@ void HWR_DrawMD2(gl_vissprite_t *spr)
skinnum = (skin_t *)spr->mobj->localskin - skins;
}
}
else if (spr->mobj->skin)
else
{
md2s = md2_playermodels;
skinnum = (skin_t *)spr->mobj->skin - skins;
+20
View File
@@ -193,6 +193,26 @@
"}\n" \
"#endif\0"
#define GLSL_SOFTWARE_FRAGMENT_SHADER_NOPAL \
"uniform sampler2D tex;\n" \
"uniform vec4 poly_color;\n" \
"uniform vec4 tint_color;\n" \
"uniform vec4 fade_color;\n" \
"uniform float lighting;\n" \
"uniform float fade_start;\n" \
"uniform float fade_end;\n" \
GLSL_DOOM_COLORMAP \
GLSL_DOOM_LIGHT_EQUATION \
"void main(void) {\n" \
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
"vec4 base_color = texel * poly_color;\n" \
"vec4 final_color = base_color;\n" \
GLSL_SOFTWARE_TINT_EQUATION \
GLSL_SOFTWARE_FADE_EQUATION \
"final_color.a = texel.a * poly_color.a;\n" \
"gl_FragColor = final_color;\n" \
"}\n" \
// hand tuned adjustments for light level calculation
#define GLSL_FLOOR_FUDGES \
"#define STARTMAP_FUDGE 1.06\n" \
+62 -65
View File
@@ -136,7 +136,8 @@ enum
{
FBO_NONE,
FBO_ARB,
FBO_EXT
FBO_EXT,
FBO_EXT_STENCIL // supports stencil attachment
};
typedef struct
@@ -160,7 +161,7 @@ GL_DEPTH24_STENCIL8 GL_DEPTH_COMPONENT_EXT
GL_DEPTH_STENCIL_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
#endif
static void GL_FBO_DeleteAttachments(void);
static void GL_Framebuffer_DeleteAttachments(void);
#endif
// needed for glportals
@@ -768,22 +769,28 @@ static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
#ifdef USE_FBO_OGL
static int GLFramebuffer_CheckExt(void)
{
// check for the standard arb extensions
// these should be there from version 3.0 onwards
// in opengl 3.0 and up fbos are standart and always supported
if (majorGL >= 3)
return FBO_ARB;
// gl versions from 2.1 may still support framebuffer objects
// maybe, just maybe, we support the standart extensions
if (GL_isExtAvailable("GL_ARB_framebuffer_no_attachments", gl_extensions) &&
GL_isExtAvailable("GL_ARB_framebuffer_object", gl_extensions) &&
GL_isExtAvailable("GL_ARB_framebuffer_sRGB", gl_extensions))
{
return FBO_ARB;
}
// gl versions from 2.1 and older may still support framebuffer objects
// depending on vendor and driver support
// nope, try the older 2.1 extensions
if (GL_isExtAvailable("GL_EXT_framebuffer_no_attachments", gl_extensions) &&
GL_isExtAvailable("GL_EXT_framebuffer_object", gl_extensions) &&
GL_isExtAvailable("GL_EXT_framebuffer_sRGB", gl_extensions) &&
GL_isExtAvailable("GL_EXT_packed_depth_stencil", gl_extensions)) // we use the stencil buffer for stuff like portals, so its better to make stencil extension a requirement
GL_isExtAvailable("GL_EXT_framebuffer_sRGB", gl_extensions))
{
// perhaps we may even support a stencil attachment
if (GL_isExtAvailable("GL_EXT_packed_depth_stencil", gl_extensions))
return FBO_EXT_STENCIL;
// no stencil support, sad
return FBO_EXT;
}
@@ -901,41 +908,36 @@ void SetupGLFunc4(void)
GL_DBG_Printf("\nFBO: ARB extensions found\n");
}
else if (fbocheck == FBO_EXT) // uh oh only support old fbo extensions...
else if (fbocheck == FBO_EXT || fbocheck == FBO_EXT_STENCIL) // uh oh only support for EXT prefix fbos...
{
GetGLfunc(glGenFramebuffersEXT);
GetGLfunc(glBindFramebufferEXT);
GetGLfunc(glDeleteFramebuffersEXT);
GetGLfunc(glFramebufferTexture2DEXT);
GetGLfunc(glCheckFramebufferStatusEXT);
GetGLfunc(glGenRenderbuffersEXT);
GetGLfunc(glBindRenderbufferEXT);
GetGLfunc(glDeleteRenderbuffersEXT);
GetGLfunc(glRenderbufferStorageEXT);
GetGLfunc(glFramebufferRenderbufferEXT);
// remapping galore huehue
// do this so we dont have to dupe half our code
GetGLfunc(glGenFramebuffersEXT);
pglGenFramebuffers = pglGenFramebuffersEXT;
GetGLfunc(glBindFramebufferEXT);
pglBindFramebuffer = pglBindFramebufferEXT;
GetGLfunc(glDeleteFramebuffersEXT);
pglDeleteFramebuffers = pglDeleteFramebuffersEXT;
GetGLfunc(glFramebufferTexture2DEXT);
pglFramebufferTexture2D = pglFramebufferTexture2DEXT;
GetGLfunc(glCheckFramebufferStatusEXT);
pglCheckFramebufferStatus = pglCheckFramebufferStatusEXT;
GetGLfunc(glGenRenderbuffersEXT);
pglGenRenderbuffers = pglGenRenderbuffersEXT;
GetGLfunc(glBindRenderbufferEXT);
pglBindRenderbuffer = pglBindRenderbufferEXT;
GetGLfunc(glDeleteRenderbuffersEXT);
pglDeleteRenderbuffers = pglDeleteRenderbuffersEXT;
GetGLfunc(glRenderbufferStorageEXT);
pglRenderbufferStorage = pglRenderbufferStorageEXT;
GetGLfunc(glFramebufferRenderbufferEXT);
pglFramebufferRenderbuffer = pglFramebufferRenderbufferEXT;
GL_DBG_Printf("\nFBO: EXT extensions with packed depth-stencil\n");
if (fbocheck == FBO_EXT)
GL_DBG_Printf("\nFBO: EXT extensions found, no stencil\n");
else if (fbocheck == FBO_EXT_STENCIL)
GL_DBG_Printf("\nFBO: EXT extensions with packed depth-stencil\n");
}
supportFBO = fbocheck;
@@ -1149,7 +1151,7 @@ void GL_SetModelView(GLint w, GLint h)
GL_FlushScreenTextures();
#ifdef USE_FBO_OGL
GL_FBO_DeleteAttachments();
GL_Framebuffer_DeleteAttachments();
#endif
}
@@ -2639,7 +2641,11 @@ void GL_SetSpecialState(hwdspecialstate_t IdState, INT32 Value)
case HWD_SET_MSAA:
if (Value)
{
pglEnable(GL_MULTISAMPLE);
if (Value == 2)
pglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
break;
case HWD_SET_TEXTUREANISOTROPICMODE:
@@ -3240,7 +3246,7 @@ void GL_SetTransform(FTransform *stransform)
}
#ifdef USE_FBO_OGL
static void GL_FBO_DeleteAttachments(void)
static void GL_Framebuffer_DeleteAttachments(void)
{
if (supportFBO == FBO_NONE || !framebufferobject.init)
return;
@@ -3260,9 +3266,9 @@ static void GL_FBO_DeleteAttachments(void)
framebufferobject.init = false;
}
static void GL_FBO_Generate(void)
static void GL_Framebuffer_Generate(void)
{
if (supportFBO == FBO_NONE || framebufferobject.init)
if (supportFBO == FBO_NONE || framebufferobject.init || !UseScreenFBO())
return;
// Generate the framebuffer
@@ -3277,7 +3283,7 @@ static void GL_FBO_Generate(void)
{
pglGenTextures(1, &framebufferobject.tex);
pglBindTexture(GL_TEXTURE_2D, framebufferobject.tex);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screen_width, screen_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
@@ -3300,13 +3306,18 @@ static void GL_FBO_Generate(void)
pglRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, screen_width, screen_height);
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
}
else if (supportFBO == FBO_EXT)
else if (supportFBO == FBO_EXT || supportFBO == FBO_EXT_STENCIL)
{
pglRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, screen_width, screen_height);
// attach the renderbuffer to depth attachment point
pglRenderbufferStorage(GL_RENDERBUFFER_EXT, (supportFBO == FBO_EXT_STENCIL) ? GL_DEPTH_STENCIL_EXT : GL_DEPTH_COMPONENT, screen_width, screen_height);
// attach a renderbuffer to depth attachment point
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
// attach the renderbuffer to stencil attachment point
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
if (supportFBO == FBO_EXT_STENCIL)
{
// attach a renderbuffer to stencil attachment point
pglFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
}
}
// Clear the renderbuffer
@@ -3318,7 +3329,7 @@ static void GL_FBO_Generate(void)
if (pglCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
{
//pglGetError(); TODO:implement this or smth
GL_MSG_Error("GL_FBO_Generate: Failed to create Framebuffer Object");
GL_MSG_Error("GL_Framebuffer_Generate: Failed to create Framebuffer Object");
// if this fails, dont retry it a gazillion times
// this wouldnt recover
@@ -3333,7 +3344,7 @@ static void GL_FBO_Generate(void)
framebufferobject.init = true;
}
void GL_FBO_BindMainFrameBuffer(void)
void GL_Framebuffer_Unbind(void)
{
if (supportFBO == FBO_NONE || !framebufferobject.init)
return;
@@ -3342,22 +3353,22 @@ void GL_FBO_BindMainFrameBuffer(void)
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
}
void GL_FBO_Enable(void)
void GL_Framebuffer_Enable(void)
{
if (supportFBO == FBO_NONE)
if (supportFBO == FBO_NONE || !UseScreenFBO())
return;
GL_FBO_Generate();
GL_Framebuffer_Generate();
// failed
if (!framebufferobject.init)
if (supportFBO == FBO_NONE || !framebufferobject.init)
return;
pglBindFramebuffer(GL_FRAMEBUFFER_EXT, framebufferobject.fboobj);
pglBindRenderbuffer(GL_RENDERBUFFER_EXT, framebufferobject.rboobj);
}
void GL_FBO_Disable(void)
void GL_Framebuffer_Disable(void)
{
if (supportFBO == FBO_NONE || !framebufferobject.init)
return;
@@ -3370,7 +3381,7 @@ void GL_FBO_Disable(void)
pglDeleteFramebuffers(1, &framebufferobject.fboobj);
framebufferobject.fboobj = 0;
GL_FBO_DeleteAttachments();
GL_Framebuffer_DeleteAttachments();
}
#endif
@@ -3721,7 +3732,6 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8
void GL_MakeScreenTexture(int tex)
{
boolean firstTime;
static GLint lastfiltermode[NUMSCREENTEXTURES] = {-1, -1, -1, -1, -1};
if (!gl_enable_screen_textures)
return;
@@ -3734,29 +3744,16 @@ void GL_MakeScreenTexture(int tex)
pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]);
// if were downsampling, choose to do that with linear filter instead of nearest neighbor
// otherwise well get ugly mixels
GLint filtermode = I_IsDownsampling() ? GL_LINEAR : GL_NEAREST;
// avoid redundant calls to this, prob doesent really matter tbh
if (filtermode != lastfiltermode[tex] || firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtermode);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtermode);
lastfiltermode[tex] = filtermode;
}
if (firstTime)
{
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
Clamp2D(GL_TEXTURE_WRAP_S);
Clamp2D(GL_TEXTURE_WRAP_T);
pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, screen_texsizew, screen_texsizeh, 0);
}
else
{
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screen_texsizew, screen_texsizeh);
}
tex_downloaded = screenTextures[tex];
}
+3 -3
View File
@@ -98,9 +98,9 @@ extern PFNglGetString pglGetString;
#endif
#ifdef USE_FBO_OGL
void GL_FBO_BindMainFrameBuffer(void);
void GL_FBO_Enable(void);
void GL_FBO_Disable(void);
void GL_Framebuffer_Unbind(void);
void GL_Framebuffer_Enable(void);
void GL_Framebuffer_Disable(void);
extern int supportFBO;
#endif
+4 -2
View File
@@ -126,9 +126,11 @@ boolean I_CheckNativeRes(void);
void I_SetBorderlessWindow(void);
#ifdef USE_FBO_OGL
void I_CheckDownSampleState(boolean forcerefresh);
boolean I_IsDownsampling(void);
void RefreshOGLSDLSurface(void);
void I_DownSample(void);
boolean UseScreenFBO(void);
extern boolean downsample;
#endif
// So we can call this from i_video event loop
+3 -1
View File
@@ -3829,8 +3829,10 @@ static void K_drawKartMinimap(void)
}
else
{
const INT32 skinnum = K_GetMobjLocalSkinNum(mobj->skin, mobj->localskin, mobj->skinlocal);
// special case if startcolor is not the default (160 / Green)
if (K_GetMobjSkin(mobj)->starttranscolor != skins[0].starttranscolor)
if (skinnum && skins[skinnum].starttranscolor != skins[0].starttranscolor)
{
colormap = R_GetTranslationColormap(TC_DEFAULT, mobj->color, GTC_CACHE);
}
+100 -163
View File
@@ -71,11 +71,12 @@ consvar_t cv_stairjank = {"stairjank", "Off", CV_SAVE|CV_CALL, CV_OnOff, PDistor
consvar_t cv_stairjanksfx = {"stairjanksfx", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
//hardcode saltyhop mhhm
consvar_t cv_saltyhop = {"hardcodehop", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static void saltyhop_onchange(void);
consvar_t cv_saltyhop = {"hardcodehop", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, saltyhop_onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltyhopsfx = {"hardcodehopsfx", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltysquish = {"hardcodehopsquish", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t saltyheight_t[] = {{FRACUNIT/4, "MIN"}, {2*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_saltyheight = {"hardcodehopheight", "1", CV_FLOAT|CV_SAVE, saltyheight_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltyheight = {"hardcodehopheight", "1", CV_FLOAT|CV_SAVE|CV_CALL|CV_NOINIT, saltyheight_t, saltyhop_onchange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_saltyroll = {"hardcodehoproll", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_squishdance = {"squishdance", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -83,6 +84,23 @@ consvar_t cv_squishdance = {"squishdance", "On", CV_SAVE, CV_OnOff, NULL, 0, NUL
static CV_PossibleValue_t squishdancespeed_cons_t[] = {{20, "MIN"}, {280, "MAX"}, {0, NULL}};
consvar_t cv_squishdancespeed = {"squishdance_speed", "140", CV_SAVE, squishdancespeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static void saltyhop_onchange(void)
{
// reset everything when toggling saltyhop
if (gamestate != GS_LEVEL)
return;
for (INT32 i = 0; i < MAXPLAYERS; i++)
{
player_t *player = &players[i];
if (!player || P_MobjWasRemoved(player->mo))
continue;
memset(&player->mo->salty, 0, sizeof(player->mo->salty));
}
}
// SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H:
// gamespeed is cc (0 for easy, 1 for normal, 2 for hard)
// franticitems is Frantic Mode items, bool
@@ -1809,56 +1827,25 @@ void K_RespawnChecker(player_t *player)
mobj_t *mo;
angle_t newangle;
fixed_t newx, newy, newz;
#ifdef PHOBOS_BUILD
const fixed_t fscale = player->mo->scale;
#else
static const fixed_t fscale = FRACUNIT; // does NOT use scale, since this effect doesn't scale properly
#endif
newangle = FixedAngle(((360/8)*i)*FRACUNIT);
newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31 * fscale);
newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31 * fscale);
newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31<<FRACBITS); // does NOT use scale, since this effect doesn't scale properly
newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31<<FRACBITS);
if (player->mo->eflags & MFE_VERTICALFLIP)
newz = player->mo->z + player->mo->height;
else
newz = player->mo->z;
mo = P_SpawnMobj(newx, newy, newz, MT_DEZLASER);
if (!P_MobjWasRemovedCompat(mo))
if (mo)
{
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->eflags |= MFE_VERTICALFLIP;
P_SetTarget(&mo->target, player->mo);
mo->angle = newangle+ANGLE_90;
mo->momz = (8 * fscale) * P_MobjFlip(player->mo);
P_SetScale(mo, (mo->destscale = fscale));
mo->momz = (8<<FRACBITS) * P_MobjFlip(player->mo);
P_SetScale(mo, (mo->destscale = FRACUNIT));
}
#ifndef PHOBOS_BUILD
// vanilla compat really is annoying.......
// but this stuff is messed up on mobjscaled maps
// and we gotta respawn it locally to avoid desynchs...
if (mapobjectscale != FRACUNIT)
{
// hide the normal lazers!
mo->flags2 |= MF2_DONTDRAW;
newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31 * player->mo->scale);
newy = player->mo->y + P_ReturnThrustY(player->mo, newangle, 31 * player->mo->scale);
// now spawn our local lazers
mo = P_SpawnMobj(newx, newy, newz, MT_DEZLASER);
if (!P_MobjWasRemovedCompat(mo))
{
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->eflags |= MFE_VERTICALFLIP;
P_SetTarget(&mo->target, player->mo);
mo->angle = newangle+ANGLE_90;
mo->momz = (8 * player->mo->scale) * P_MobjFlip(player->mo);
P_SetScale(mo, (mo->destscale = player->mo->scale));
mo->islocal = true; // Keep this local!
}
}
#endif
}
}
}
@@ -2207,7 +2194,7 @@ static void K_GetKartBoostPower(player_t *player)
// Technically, all mobjs that think can cause desynchs if they are spawned conditionally, so best we can do
// is to hide them if you are in saltyhop jump
if (dust && player->salty.jump)
if (dust && player->mo->salty.jump)
dust->flags2 |= MF2_DONTDRAW;
if (leveltime % 6 == 0)
@@ -3236,8 +3223,10 @@ static void K_SpawnDriftSparks(player_t *player)
for (i = 0; i < 2; i++)
{
const angle_t thrustangle = (travelangle + ((i&1) ? -1 : 1)*ANGLE_135);
const fixed_t smolscale = FixedMul(32*FRACUNIT, player->mo->scale);
fixed_t driftExtraScale = 0;
angle_t thrustangle = (travelangle + ((i&1) ? -1 : 1)*ANGLE_135);
fixed_t smolscale = FixedMul(32*FRACUNIT, player->mo->scale);
newx = player->mo->x + P_ReturnThrustX(player->mo, thrustangle, smolscale);
newy = player->mo->y + P_ReturnThrustY(player->mo, thrustangle, smolscale);
@@ -3249,9 +3238,9 @@ static void K_SpawnDriftSparks(player_t *player)
spark->angle = travelangle-(ANGLE_45/5)*player->kartstuff[k_drift];
// scale increase while driftspark level gained timer is running
const fixed_t driftExtraScale = FixedDiv(player->driftsparkGrowTimer, DRIFTSPARKGROWTICS);
driftExtraScale = FixedDiv(player->driftsparkGrowTimer, DRIFTSPARKGROWTICS);
spark->destscale = FixedMul(player->mo->scale, FRACUNIT + FixedMul(driftExtraScale, cv_driftsparkpulse.value));
P_SetScale(spark, spark->destscale);
P_SetScale(spark, spark->destscale); // why not use what we calculated above?
spark->momx = player->mo->momx/2;
spark->momy = player->mo->momy/2;
@@ -3343,10 +3332,10 @@ static void K_StretchPlayerGravity(player_t *player)
mobj_t *pmo = player->mo;
const fixed_t tempxscale = pmo->realxscale;
const fixed_t tempyscale = pmo->realyscale;
fixed_t tempxscale = pmo->realxscale;
fixed_t tempyscale = pmo->realyscale;
stretchScaleFactor = FixedDiv(mapobjectscale*60, cv_gravstretch.value);
stretchScaleFactor = FixedDiv(FRACUNIT*60, cv_gravstretch.value);
stretchScaleFactor = min(stretchScaleFactor, MAXSTRETCHDIV);
if (pmo->slamsoundtimer)
@@ -3354,26 +3343,26 @@ static void K_StretchPlayerGravity(player_t *player)
if (!P_IsObjectOnGround(pmo))
{
const fixed_t pzmom = abs(pmo->momz);
fixed_t pzmom = abs(pmo->momz);
const fixed_t stretchDiv = FixedDiv(pzmom, stretchScaleFactor);
if (abs(pzmom/mapobjectscale) != 0)
if (abs(pzmom/FRACUNIT) != 0)
{
if ((tempxscale - stretchDiv) > (tempxscale / 5))
if (((tempxscale-(stretchDiv))) > (tempxscale/5))
{
pmo->spritexscale = (tempxscale - stretchDiv);
pmo->stretchslam = pzmom;
}
else
pmo->spritexscale = (tempxscale / 5);
pmo->spritexscale = (tempxscale/5);
pmo->spriteyscale = (tempyscale + ((stretchDiv * 2) / 3));
pmo->spriteyscale = (tempyscale + ((stretchDiv*2)/3));
}
}
else if (pmo->stretchslam > 0)
{
// Funni slam sound when landing
if (cv_slamsound.value && (pmo->eflags & MFE_JUSTHITFLOOR) && !pmo->slamsoundtimer && (pmo->stretchslam > 4*mapobjectscale))
if (cv_slamsound.value && (pmo->eflags & MFE_JUSTHITFLOOR) && !pmo->slamsoundtimer && (pmo->stretchslam > 4*FRACUNIT))
{
S_StartSound(pmo, sfx_s3k4c);
pmo->slamsoundtimer = TICRATE;
@@ -3381,9 +3370,9 @@ static void K_StretchPlayerGravity(player_t *player)
const fixed_t slamDiv = FixedDiv(pmo->stretchslam, stretchScaleFactor);
pmo->spritexscale = (tempxscale + (((slamDiv * 2) / 3 ) * 2));
pmo->spritexscale = (tempxscale + (((slamDiv*2)/3)*2));
pmo->spriteyscale = (tempyscale - slamDiv);
pmo->stretchslam -= (4*mapobjectscale);
pmo->stretchslam -= (4*FRACUNIT);
}
else
pmo->stretchslam = 0;
@@ -3398,16 +3387,16 @@ static void K_SaltySquish(player_t *player)
mobj_t *pmo = player->mo;
const fixed_t tempxscale = pmo->realxscale;
const fixed_t tempyscale = pmo->realyscale;
fixed_t tempxscale = pmo->realxscale;
fixed_t tempyscale = pmo->realyscale;
if (pmo->stretchslam > 0)
{
const fixed_t slamDiv = FixedDiv(pmo->stretchslam, mapobjectscale*60); // stretchScaleFactor = FixedDiv(mapobjectscale*60, FRACUNIT)
const fixed_t slamDiv = FixedDiv(pmo->stretchslam, FRACUNIT*60); // stretchScaleFactor = FixedDiv(FRACUNIT*60, FRACUNIT)
pmo->spritexscale = (tempxscale + (((slamDiv * 2) / 3) * 2));
pmo->spritexscale = (tempxscale + (((slamDiv*2)/3)*2));
pmo->spriteyscale = (tempyscale - slamDiv);
pmo->stretchslam -= (4*mapobjectscale);
pmo->stretchslam -= (4*FRACUNIT);
}
else
pmo->stretchslam = 0;
@@ -3415,92 +3404,88 @@ static void K_SaltySquish(player_t *player)
static void K_QuiteSaltyHop(player_t *player)
{
I_Assert(player != NULL);
I_Assert(!P_MobjWasRemoved(player->mo));
if (!cv_saltyhop.value)
return;
// what the fuck is this haya
mobj_t *pmo = player->mo;
salty_t *psalty = &player->salty;
if (!cv_saltyhop.value)
{
// reset before we leave
psalty->jump = psalty->ready = psalty->tapping = false;
psalty->momz = psalty->zoffset = 0;
return;
}
salty_t *psalt = &pmo->salty;
const boolean onground = P_IsObjectOnGround(pmo);
// ready?
if (!player->kartstuff[k_jmp])
{
psalty->ready = true;
psalty->tapping = false;
psalt->ready = true;
psalt->tapping = false;
}
else if (psalty->ready)
else if (psalt->ready)
{
psalty->ready = false;
psalty->tapping = true;
psalt->ready = false;
psalt->tapping = true;
}
else
{
psalty->tapping = false;
psalt->tapping = false;
}
// GO!
if (psalty->jump)
if (!psalt->init)
{
psalt->jump = false;
psalt->zoffset = 0;
psalt->momz = 0;
psalt->init = true;
}
else if (psalt->jump)
{
if (pmo->eflags & MFE_JUSTHITFLOOR)
{
psalty->zoffset = 0;
psalt->zoffset = 0;
}
else if (onground)
{
psalty->zoffset += psalty->momz;
psalty->momz -= (FRACUNIT*3/2);
psalt->zoffset += psalt->momz;
psalt->momz -= (FRACUNIT*3/2);
}
else
{
//psalty->zoffset *= (49/50)*FRACUNIT; // this just rounds down to 0 lol
psalty->zoffset = 0;
psalty->momz = 0;
psalt->zoffset *= (49/50)*FRACUNIT;
psalt->momz = 0;
}
if (psalty->zoffset <= 0)
if (psalt->zoffset <= 0)
{
if (cv_saltyhopsfx.value && !(pmo->eflags & MFE_JUSTHITFLOOR) && onground)
S_StartSound(pmo, sfx_s268);
psalty->jump = false;
psalty->zoffset = 0;
psalty->momz = 0;
psalt->jump = false;
psalt->zoffset = 0;
psalt->momz = 0;
// shlamma damma
if (cv_saltysquish.value)
pmo->stretchslam += 8*mapobjectscale;
pmo->stretchslam += 8*FRACUNIT;
}
else if (psalty->zoffset > 0)
else if (cv_saltysquish.value && psalt->zoffset >= 0)
{
if (cv_saltysquish.value)
{
// goofy ahh hack
pmo->spriteyscale += (FRACUNIT/8);
pmo->spritexscale -= (FRACUNIT/8);
}
// goofy ahh hack
pmo->spriteyscale += (FRACUNIT/8);
pmo->spritexscale -= (FRACUNIT/8);
}
pmo->spriteyoffset += FixedMul(psalty->zoffset, cv_saltyheight.value);
pmo->spriteyoffset += FixedMul(psalt->zoffset, cv_saltyheight.value);
// Stop any and all drift sounds when hopping.
if (S_SoundPlaying(pmo, sfx_screec))
S_StopSoundByID(pmo, sfx_screec);
if (S_SoundPlaying(pmo, sfx_drift))
S_StopSoundByID(pmo, sfx_drift);
if (cv_saltyhopsfx.value)
{
if (S_SoundPlaying(pmo, sfx_screec))
S_StopSoundByID(pmo, sfx_screec);
if (S_SoundPlaying(pmo, sfx_drift))
S_StopSoundByID(pmo, sfx_drift);
}
}
else if (psalty->tapping && onground && !player->kartstuff[k_spinouttimer] && !player->kartstuff[k_squishedtimer])
else if (psalt->tapping && onground && !player->kartstuff[k_spinouttimer] && !player->kartstuff[k_squishedtimer])
{
psalty->jump = true;
psalty->zoffset = 0;
psalty->momz = 6*FRACUNIT;
psalt->jump = true;
psalt->zoffset = 0;
psalt->momz = 6*FRACUNIT;
if (cv_saltyhopsfx.value)
S_StartSound(pmo, sfx_s25a);
}
@@ -3527,7 +3512,7 @@ boolean K_ShouldSlopeRoll(mobj_t *mobj)
return false;
// seeing a character rotate mid-hop looks really janky
if (!cv_saltyroll.value && mobj->player && mobj->player->salty.jump)
if (!cv_saltyroll.value && mobj->player && mobj->player->mo->salty.jump)
return false;
return K_CheckSlopeRollDist(mobj);
@@ -3739,7 +3724,7 @@ mobj_t *K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent)
dust = P_SpawnMobj(rand_x, rand_y, mo->z, MT_WIPEOUTTRAIL);
P_SetTarget(&dust->target, mo);
dust->angle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
dust->angle = R_PointToAngle2(0,0,mo->momx,mo->momy);
dust->destscale = mo->scale;
P_SetScale(dust, mo->scale);
K_FlipFromObject(dust, mo);
@@ -3765,11 +3750,6 @@ mobj_t *K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent)
void K_DriftDustHandling(mobj_t *spawner)
{
angle_t anglediff;
#ifdef PHOBOS_BUILD
const fixed_t fscale = spawner->scale;
#else
static const fixed_t fscale = FRACUNIT; // should be spawner->scale but the below calls P_Random!
#endif
if (leveltime % 2 != 0 || !P_IsObjectOnGround(spawner))
return;
@@ -3786,7 +3766,7 @@ void K_DriftDustHandling(mobj_t *spawner)
{
angle_t playerangle = spawner->angle;
if (spawner->player->speed < (5 * fscale))
if (spawner->player->speed < 5<<FRACBITS)
return;
if (spawner->player->cmd.forwardmove < 0)
@@ -3797,7 +3777,7 @@ void K_DriftDustHandling(mobj_t *spawner)
}
else
{
if (P_AproxDistance(spawner->momx, spawner->momy) < (5 * fscale))
if (P_AproxDistance(spawner->momx, spawner->momy) < 5<<FRACBITS)
return;
anglediff = abs((signed)(spawner->angle - R_PointToAngle2(0, 0, spawner->momx, spawner->momy)));
@@ -3810,29 +3790,13 @@ void K_DriftDustHandling(mobj_t *spawner)
if (anglediff > ANG10*4) // Trying to turn further than 40 degrees
{
mobj_t *dust = NULL;
fixed_t spawnx = P_RandomRange(-spawnrange, spawnrange)<<FRACBITS;
fixed_t spawny = P_RandomRange(-spawnrange, spawnrange)<<FRACBITS;
INT32 speedrange = 2;
dust = P_SpawnMobj(spawner->x + spawnx, spawner->y + spawny, spawner->z, MT_DRIFTDUST);
const INT32 momxrand = P_RandomRange(-speedrange, speedrange);
const INT32 momyrand = P_RandomRange(-speedrange, speedrange);
const INT32 momzrand = P_RandomRange(1, 4);
if (P_MobjWasRemovedCompat(dust))
return;
#ifdef PHOBOS_BUILD
dust->momx = FixedMul(spawner->momx + (momxrand * spawner->scale), 3*FRACUNIT/4);
dust->momy = FixedMul(spawner->momy + (momyrand * spawner->scale), 3*FRACUNIT/4);
#else
dust->momx = FixedMul(spawner->momx + (momxrand<<FRACBITS), 3*(spawner->scale)/4);
dust->momy = FixedMul(spawner->momy + (momyrand<<FRACBITS), 3*(spawner->scale)/4);
#endif
dust->momz = P_MobjFlip(spawner) * (momzrand * (spawner->scale));
mobj_t *dust = P_SpawnMobj(spawner->x + spawnx, spawner->y + spawny, spawner->z, MT_DRIFTDUST);
dust->momx = FixedMul(spawner->momx + (P_RandomRange(-speedrange, speedrange)<<FRACBITS), 3*(spawner->scale)/4);
dust->momy = FixedMul(spawner->momy + (P_RandomRange(-speedrange, speedrange)<<FRACBITS), 3*(spawner->scale)/4);
dust->momz = P_MobjFlip(spawner) * (P_RandomRange(1, 4) * (spawner->scale));
P_SetScale(dust, spawner->scale/2);
dust->destscale = spawner->scale * 3;
dust->scalespeed = spawner->scale/12;
@@ -3841,33 +3805,6 @@ void K_DriftDustHandling(mobj_t *spawner)
S_StartSound(spawner, sfx_screec);
K_MatchGenericExtraFlags(dust, spawner);
#ifndef PHOBOS_BUILD
// vanilla compat really is annoying.......
// but this stuff is messed up on mobjscaled maps
// and we gotta respawn it locally to avoid desynchs...
if (mapobjectscale != FRACUNIT)
{
// hide the normal dust!
dust->flags2 |= MF2_DONTDRAW;
// now spawn our dust locally
dust = P_SpawnMobj(spawner->x + spawnx, spawner->y + spawny, spawner->z, MT_DRIFTDUST);
if (P_MobjWasRemovedCompat(dust))
return;
dust->momx = FixedMul(spawner->momx + (momxrand * spawner->scale), 3*FRACUNIT/4);
dust->momy = FixedMul(spawner->momy + (momyrand * spawner->scale), 3*FRACUNIT/4);
dust->momz = P_MobjFlip(spawner) * (momzrand * (spawner->scale));
P_SetScale(dust, spawner->scale/2);
dust->destscale = spawner->scale * 3;
dust->scalespeed = spawner->scale/12;
dust->islocal = true; // Keep this local!
K_MatchGenericExtraFlags(dust, spawner);
}
#endif
}
}
+1 -6
View File
@@ -182,19 +182,14 @@ void COM_Lua_f(void)
len = (argc+1)*256;
buf = malloc(len);
if (buf == NULL)
I_Error("Failed to allocate buffer for COM_Lua_f");
p = buf;
WRITEUINT8(p, argc);
for (i = 0; i < argc; i++)
WRITESTRINGN(p, COM_Argv(i), 255);
if (flags & COM_SPLITSCREEN)
if (flags & 2)
SendNetXCmdForPlayer(1, XD_LUACMD, buf, p-buf);
else
SendNetXCmd(XD_LUACMD, buf, p-buf);
free(buf);
return;
}
+2 -11
View File
@@ -13,12 +13,6 @@
#include <string.h>
#ifdef HAVE_THREADS
#define local_for_thread _Thread_local
#else
#define local_for_thread
#endif
#include "doomdef.h"
#include "command.h"
#include "m_argv.h"
@@ -37,11 +31,8 @@ char **myargv = NULL;
boolean myargmalloc = false;
/** \brief founded the parm
*
* thread_local because it can potentially be used from multiple threads (global variables aaaaaa)
* (myargc and myargv don't have to be thread_local because they are never modified after being set up)
*/
static local_for_thread INT32 found;
static INT32 found;
/** \brief The M_CheckParm function
@@ -100,7 +91,7 @@ INT32 M_CheckProtoParam(const char *check)
const char *M_GetProtoParam(void)
{
INT32 i;
char *string;
static char *string;
for (i = 1; i < myargc; i++)
{
+20 -42
View File
@@ -3984,14 +3984,6 @@ menudemo_t *demolist = NULL; // Replays that that have been checked to match wit
menudemo_t *demolist_all = NULL; // All replays
size_t demolist_all_size = 0;
boolean replaynamesloaded = false;
// Whenever we start a replay load thread, we increment this number and then thread will remember current value,
// and by the end it will compare it with current value, and if it is equal it means thread can store data it has loaded.
// If it's not equal, that means we started more than one thread (left and re-entered menu for example)
size_t replaythreadnum = 0;
// for replay dates
#include <locale.h>
const char *demodateformat = "%d.%m.%Y";
#ifdef HAVE_THREADS
I_mutex replayquerymutex;
@@ -4021,15 +4013,12 @@ static SINT8 replayScrollDelay = TICRATE, replayScrollDir = 1;
static void ReplayNamesLoadThread(void* userdata)
{
(void)userdata;
Lock_search_state();
size_t demolist_all_size_local = demolist_all_size;
menudemo_t *demolist_all_local = (menudemo_t*)malloc(sizeof(menudemo_t)*demolist_all_size_local);
memcpy(demolist_all_local, demolist_all, sizeof(menudemo_t)*demolist_all_size_local);
size_t localreplaythreadnum = replaythreadnum;
const char *localdemodateformat = demodateformat;
char *replaydirpath = (char*)userdata;
Unlock_search_state();
@@ -4037,13 +4026,19 @@ static void ReplayNamesLoadThread(void* userdata)
{
if (demolist_all_local[i].type != MD_SUBDIR)
{
G_LoadDemoTitle(&demolist_all_local[i], localdemodateformat);
G_LoadDemoTitle(&demolist_all_local[i]);
// this is fucking horrid, but i wanna be able to search for dates
/*if (demolist_all_local[i].date[0] != '\0')
{
snprintf(demolist_all_local[i].title, sizeof(demolist_all_local[i].title), "%s %s", demolist_all_local[i].title, demolist_all_local[i].date);
}*/
}
}
Lock_search_state();
if (replaythreadnum == localreplaythreadnum && demolist_all)
if (fastcmp(menupath, replaydirpath) && demolist_all)
{
memcpy(demolist_all, demolist_all_local, sizeof(menudemo_t)*demolist_all_size);
replaynamesloaded = true;
@@ -4052,32 +4047,22 @@ static void ReplayNamesLoadThread(void* userdata)
Unlock_search_state();
// Was allocated before thread start, we need to free it
free(replaydirpath);
free(demolist_all_local);
}
static void LoadReplayNames(void)
{
char *replaydirpath = strdup(menupath);
Lock_search_state();
replaythreadnum++;
replaynamesloaded = false;
if (cv_demodateformat.value == 2)
demodateformat = "%m.%d.%Y";
else if (cv_demodateformat.value == 1)
demodateformat = "%d.%m.%Y";
else
{
// get the date format here
// setlocale reads/writes global state
const char *locale = setlocale(LC_TIME, NULL);
// US ppl are special (:
demodateformat = (locale && strstr(locale, "en_US")) ? "%m.%d.%Y" : "%d.%m.%Y";
}
Unlock_search_state();
#ifdef HAVE_THREADS
I_spawn_thread("replay-names-load", ReplayNamesLoadThread, NULL);
I_spawn_thread("replay-names-load", ReplayNamesLoadThread, replaydirpath);
#else
ReplayNamesLoadThread(NULL);
ReplayNamesLoadThread(replaydirpath);
#endif
}
@@ -4116,12 +4101,8 @@ static void M_HutCheckReplays(size_t maxnum)
// Mark as done
replayqueryfound = replayquerycheck = sizedirmenu;
Lock_search_state();
memcpy(demolist, demolist_all, sizeof(menudemo_t) * sizedirmenu);
Unlock_search_state();
return;
}
@@ -4270,15 +4251,13 @@ static boolean M_HandleReplayHutQuery(INT32 choice)
char tmp[MAXREPLAYQUERY+1];
memcpy(tmp, replayqueryinput_buffer, MAXREPLAYQUERY+1);
// Honestly not sure if locks for replaynamesloaded are necessary...
// Thread sanitizer does report race condition whenever replaynamesloaded is accessed without lock
// but really it is only ever set to false in main thread and only set to true in replay load thread,
// and both are done via locks. If replaynamesloaded is true, it is never gonna suddenly switch from true to false
// while we're in main thread, and if it would switch from false to true it is not really a big deal, we will just skip
// 1 frame where replay names were loaded
Lock_search_state();
if (!replaynamesloaded)
{
Unlock_search_state();
return false;
}
Unlock_search_state();
if (M_TextInputHandle(&replayqueryinput, choice))
{
@@ -9950,7 +9929,6 @@ static void M_DrawLocalSkinMenu(void)
V_DrawFill(mx + 220 - (charw/2), my+54, charw, 84, 239);
#undef charw
// FIXME: is skins[displayskin.localnum] even correct?
UINT8 *colormap = R_GetLocalTranslationColormap(&skins[displayskin.localnum], (displayskin.localskin ? &localskins[displayskin.localnum] : NULL), cv_playercolor.value, GTC_MENUCACHE, displayskin.localskin);
V_DrawMappedPatch(mx, my+50, 0, (patch_t *)W_CachePatchName(displayskin.facewant, PU_PATCH), colormap);
@@ -9968,7 +9946,7 @@ static void M_DrawLocalSkinMenu(void)
my += 120;
#ifdef HWRENDER
md2_t *md2 = (displayskin.localskin ? &md2_localplayermodels[displayskin.localnum] : &md2_playermodels[skintodisplay]);
md2_t *md2 = (displayskin.localskin ? &md2_localplayermodels[skintodisplay] : &md2_playermodels[skintodisplay]);
// if we have 3d models enabled and a model exists
// try to show it instead of the sprite
+60 -102
View File
@@ -6280,39 +6280,16 @@ static void P_MobjSceneryThink(mobj_t *mobj)
case MT_SMOLDERING:
if (leveltime % 2 == 0)
{
mobj_t *smoke;
fixed_t x = P_RandomRange(-35, 35)*mobj->scale;
fixed_t y = P_RandomRange(-35, 35)*mobj->scale;
fixed_t z = P_RandomRange(0, 70)*mobj->scale;
smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
P_SetMobjState(smoke, S_OPAQUESMOKE1);
K_MatchGenericExtraFlags(smoke, mobj);
smoke->scale = mobj->scale * 2;
smoke->destscale = mobj->scale * 6;
const INT32 momrand = P_RandomRange(4, 9);
#ifdef PHOBOS_BUILD
smoke->momz = momrand*mobj->scale*P_MobjFlip(smoke);
#else
smoke->momz = momrand*FRACUNIT*P_MobjFlip(smoke);
// vanilla compat really is annoying.......
// but this stuff is messed up on mobjscaled maps
// so we gotta respawn it locally to avoid desynchs...
if (mapobjectscale != FRACUNIT)
{
// hide the smoke!
smoke->flags2 |= MF2_DONTDRAW;
smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
P_SetMobjState(smoke, S_OPAQUESMOKE1);
K_MatchGenericExtraFlags(smoke, mobj);
smoke->scale = mobj->scale * 2;
smoke->destscale = mobj->scale * 6;
smoke->momz = momrand*mobj->scale*P_MobjFlip(smoke);
smoke->islocal = true; // Keep this local!
}
#endif
smoke->momz = P_RandomRange(4, 9)*FRACUNIT*P_MobjFlip(smoke);
}
break;
case MT_BOOMPARTICLE:
@@ -9187,12 +9164,6 @@ static boolean P_MobjPushableThink(mobj_t *mobj)
static void P_FiringThink(mobj_t *mobj)
{
if (!mobj->target)
return;
if (mobj->health <= 0)
return;
if (mobj->state->action == (actionf_p1)A_Boss1Laser)
{
var1 = mobj->state->var1;
@@ -9255,12 +9226,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->flags2 &= ~MF2_PUSHED;
mobj->eflags &= ~(MFE_SPRUNG|MFE_JUSTBOUNCEDWALL);
#ifdef PHOBOS_BUILD
P_SetTarget(&tmfloorthing, NULL);
P_SetTarget(&tmhitthing, NULL);
#else
tmfloorthing = tmhitthing = NULL;
#endif
// do NOT trigger linedef executors for "local" mobjs
if (!mobj->islocal)
@@ -9276,13 +9242,8 @@ void P_MobjThinker(mobj_t *mobj)
}
if (mobj->scale != mobj->destscale)
{
P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale.
if (P_MobjWasRemovedCompat(mobj))
return;
}
if (!mobj->player)
{
if (mobj->type == MT_GHOST && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY!
@@ -9327,21 +9288,6 @@ void P_MobjThinker(mobj_t *mobj)
{
if (!P_MobjDeadThink(mobj))
return;
// Fading tile
if (mobj->type >= MT_BOUNCEPICKUP && mobj->type <= MT_GRENADEPICKUP)
{
INT32 value = mobj->info->damage/10;
value = mobj->fuse/value;
value = 10-value;
value--;
if (value <= 0)
value = 1;
mobj->frame &= ~FF_TRANSMASK;
mobj->frame |= value << FF_TRANSSHIFT;
}
}
else
{
@@ -9352,7 +9298,7 @@ void P_MobjThinker(mobj_t *mobj)
if (P_MobjWasRemoved(mobj))
return;
if (mobj->flags2 & MF2_FIRING)
if (mobj->flags2 & MF2_FIRING && mobj->target && mobj->health > 0)
P_FiringThink(mobj);
if (mobj->flags & MF_AMBIENT)
@@ -9419,27 +9365,23 @@ void P_MobjThinker(mobj_t *mobj)
P_ButteredSlope(mobj);
}
if (mobj->health)
if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health &&
P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz
{
// extra pit check in case these didn't have momz
if ((mobj->flags & (MF_ENEMY|MF_BOSS)) &&
P_CheckDeathPitCollide(mobj))
P_KillMobj(mobj, NULL, NULL);
return;
}
// Crush enemies!
if (mobj->ceilingz - mobj->floorz < mobj->height)
{
if (((mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->flags & MF_SHOOTABLE) || mobj->type == MT_EGGSHIELD) &&
!(mobj->flags & MF_NOCLIPHEIGHT) &&
mobj->health > 0)
{
P_KillMobj(mobj, NULL, NULL);
return;
}
// Crush enemies!
if ((mobj->ceilingz - mobj->floorz) < mobj->height)
{
if ((((mobj->flags & (MF_ENEMY|MF_BOSS)) && (mobj->flags & MF_SHOOTABLE)) || mobj->type == MT_EGGSHIELD) &&
!(mobj->flags & MF_NOCLIPHEIGHT) &&
mobj->health > 0)
{
P_KillMobj(mobj, NULL, NULL);
return;
}
}
}
if (P_MobjWasRemovedCompat(mobj))
@@ -9447,6 +9389,24 @@ void P_MobjThinker(mobj_t *mobj)
// Can end up here if a player dies.
P_CycleMobjState(mobj);
if (P_MobjWasRemoved(mobj))
return;
if ((mobj->health == 0) && // Fading tile
(mobj->type >= MT_BOUNCEPICKUP && mobj->type <= MT_GRENADEPICKUP))
{
INT32 value = mobj->info->damage/10;
value = mobj->fuse/value;
value = 10-value;
value--;
if (value <= 0)
value = 1;
mobj->frame &= ~FF_TRANSMASK;
mobj->frame |= value << FF_TRANSSHIFT;
}
}
// Quick, optimized function for the Rail Rings
@@ -9700,13 +9660,20 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
// All mobjs are created at 100% scale.
mobj->scale = FRACUNIT;
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
mobj->destscale = mobj->scale;
mobj->scalespeed = FRACUNIT/12;
if (mapobjectscale != FRACUNIT) //&& !(mobj->type == MT_BLACKEGGMAN)
{
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
}
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->realxscale = mobj->realyscale =
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->realxscale = mobj->realyscale = mobj->scale;
mobj->spritexscale = mobj->realxscale;
mobj->spriteyscale = mobj->realyscale;
// set subsector and/or block links
P_SetThingPosition(mobj);
@@ -10148,13 +10115,20 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster)
// All mobjs are created at 100% scale.
mobj->scale = FRACUNIT;
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
mobj->destscale = mobj->scale;
mobj->scalespeed = FRACUNIT/12;
if (mapobjectscale != FRACUNIT) //&& !(mobj->type == MT_BLACKEGGMAN)
{
mobj->destscale = mapobjectscale;
mobj->scalespeed = mapobjectscale/12;
}
// Sprite rendering
mobj->blendmode = AST_TRANSLUCENT;
mobj->realxscale = mobj->realyscale =
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->realxscale = mobj->realyscale = mobj->scale;
mobj->spritexscale = mobj->realxscale;
mobj->spriteyscale = mobj->realyscale;
// set subsector and/or block links
P_SetThingPosition(mobj);
@@ -10254,9 +10228,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
P_CalculatePrecipFloor(mobj);
if (mobj->floorz != starting_floorz)
{
; //mobj->precipflags |= PCF_FOF;
}
mobj->precipflags |= PCF_FOF;
else
{
const INT32 special = GETSECSPECIAL(mobj->subsector->sector->special, 1);
@@ -10390,13 +10362,7 @@ void P_RemoveMobj(mobj_t *mobj)
// clear the reference from the mapthing
if (mobj->spawnpoint)
{
#ifdef PHOBOS_BUILD
P_SetTarget(&mobj->spawnpoint->mobj, NULL);
#else
mobj->spawnpoint->mobj = NULL;
#endif
}
R_RemoveMobjInterpolator(mobj);
@@ -10607,9 +10573,6 @@ void P_PrecipitationEffects(void)
P_SpawnLightningFlash(ss); // Spawn a quick flash thinker
}
if (sound_disabled)
return; // Sound off? D'aw, no fun.
const mobj_t *pmo = players[displayplayers[0]].mo;
// Local effects from here on out!
@@ -10617,6 +10580,9 @@ void P_PrecipitationEffects(void)
if (!playeringame[displayplayers[0]] || !pmo)
return;
if (sound_disabled)
return; // Sound off? D'aw, no fun.
const boolean sounds_rain = ((cv_drawdist_precip.value != 0) && rainsfx && (!leveltime || leveltime % 80 == 1));
if (!sounds_rain && !sounds_thunder)
@@ -10864,9 +10830,7 @@ void P_SpawnPlayer(INT32 playernum)
mobj_t *mobj;
if (p->playerstate == PST_REBORN)
{
G_PlayerReborn(playernum);
}
for (i = 0; i < MAXPLAYERS; i++)
{
@@ -10940,15 +10904,9 @@ void P_SpawnPlayer(INT32 playernum)
}
mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER);
I_Assert(mobj != NULL);
#ifdef PHOBOS_BUILD
mobj->player = p;
P_SetTarget(&p->mo, mobj);
#else
(mobj->player = p)->mo = mobj;
#endif
//P_SetTarget(&p->mo, mobj);
mobj->angle = mobj->old_angle = 0;
+17 -3
View File
@@ -258,12 +258,23 @@ typedef enum
// PRECIPITATION flags ?! ?! ?!
//
typedef enum {
PCF_INVISIBLE = 1, // Don't draw.
PCF_INVISIBLE = 1, // Don't draw.
PCF_PIT = 1<<1, // Above pit.
PCF_SPLASH = 1<<2, // Splashed on the ground, return to the ceiling after the animation's over
PCF_THUNK = 1<<3, // Ran the thinker this tic.
PCF_FOF = 1<<2, // Above FOF.
PCF_MOVINGFOF = 1<<3, // Above MOVING FOF (this means we need to keep floorz up to date...)
PCF_SPLASH = 1<<4, // Splashed on the ground, return to the ceiling after the animation's over
PCF_THUNK = 1<<5, // Ran the thinker this tic.
} precipflag_t;
typedef struct salty_s
{
bool init;
bool ready;
bool tapping;
fixed_t zoffset;
fixed_t momz;
bool jump;
} salty_t;
// Map Object definition.
typedef struct mobj_s
@@ -401,6 +412,9 @@ typedef struct mobj_s
tic_t slamsoundtimer; // Funni slam sound when landing
// saltyhop! hardcode edition
salty_t salty;
// WARNING: New fields must be added separately to savegame and Lua.
boolean islocal; // BEWARE: islocal does not exist in vanilla, strictly to be used for locally loaded addons to not cause desynchs with the mobj linedef trigger check. DO NOT USE THIS IN ACTUAL ADDONS YOU INTEND TO USE ON YOUR SERVER
} mobj_t;
-36
View File
@@ -1109,10 +1109,6 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242)
return;
// do not send over locally spawned mobjs
if (mobj->islocal)
return;
if (mobj->spawnpoint && mobj->info->doomednum != -1)
{
// spawnpoint is not modified but we must save it since it is an identifier
@@ -1138,17 +1134,9 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0)
#endif
diff |= MD_MOM;
#ifdef PHOBOS_BUILD
if (mobj->radius != FixedMul(mapobjectscale, mobj->info->radius))
#else
if (mobj->radius != mobj->info->radius)
#endif
diff |= MD_RADIUS;
#ifdef PHOBOS_BUILD
if (mobj->height != FixedMul(mapobjectscale, mobj->info->height))
#else
if (mobj->height != mobj->info->height)
#endif
diff |= MD_HEIGHT;
if (mobj->flags != mobj->info->flags)
diff |= MD_FLAGS;
@@ -1191,19 +1179,11 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff |= MD_MOVEFACTOR;
if (mobj->fuse)
diff |= MD_FUSE;
#ifdef PHOBOS_BUILD
if (mobj->watertop != INT32_MAX)
#else
if (mobj->watertop)
#endif
diff |= MD_WATERTOP;
if (mobj->waterbottom)
diff |= MD_WATERBOTTOM;
#ifdef PHOBOS_BUILD
if (mobj->scale != mapobjectscale)
#else
if (mobj->scale != FRACUNIT)
#endif
diff |= MD_SCALE;
if (mobj->destscale != mobj->scale)
diff |= MD_DSCALE;
@@ -2110,19 +2090,11 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
if (diff & MD_RADIUS)
mobj->radius = READFIXED(save->p);
else
#ifdef PHOBOS_BUILD
mobj->radius = FixedMul(mobj->info->radius, mapobjectscale);
#else
mobj->radius = mobj->info->radius;
#endif
if (diff & MD_HEIGHT)
mobj->height = READFIXED(save->p);
else
#ifdef PHOBOS_BUILD
mobj->height = FixedMul(mobj->info->height, mapobjectscale);
#else
mobj->height = mobj->info->height;
#endif
if (diff & MD_FLAGS)
mobj->flags = READUINT32(save->p);
else
@@ -2194,20 +2166,12 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
mobj->fuse = READINT32(save->p);
if (diff & MD_WATERTOP)
mobj->watertop = READFIXED(save->p);
#ifdef PHOBOS_BUILD
else
mobj->watertop = INT32_MAX;
#endif
if (diff & MD_WATERBOTTOM)
mobj->waterbottom = READFIXED(save->p);
if (diff & MD_SCALE)
mobj->scale = READFIXED(save->p);
else
#ifdef PHOBOS_BUILD
mobj->scale = mapobjectscale;
#else
mobj->scale = FRACUNIT;
#endif
if (diff & MD_DSCALE)
mobj->destscale = READFIXED(save->p);
else
+7 -18
View File
@@ -570,13 +570,13 @@ static void P_LoadSegs(UINT8 *data)
if (seg->sidedef == &sides[seg->linedef->sidenum[0]])
{
seg->v1 = lines[rawlinedef].v1;
seg->v2 = lines[rawlinedef].v2;
seg->v1 = lines[ms->linedef].v1;
seg->v2 = lines[ms->linedef].v2;
}
else
{
seg->v1 = lines[rawlinedef].v2;
seg->v2 = lines[rawlinedef].v1;
seg->v1 = lines[ms->linedef].v2;
seg->v2 = lines[ms->linedef].v1;
}
}
else
@@ -584,6 +584,7 @@ static void P_LoadSegs(UINT8 *data)
seg->v1 = &vertexes[v1];
seg->v2 = &vertexes[v2];
}
#ifdef HWRENDER
if (rendermode == render_opengl)
{
@@ -596,6 +597,7 @@ static void P_LoadSegs(UINT8 *data)
//seg->fv2.z = FixedToFloat(seg->v2->z);
}
#endif
seg->length = P_SegLength(seg);
P_UpdateSegLightOffset(seg);
@@ -2094,13 +2096,6 @@ static void P_LoadMapBSP(const virtres_t* virt)
virtlump_t* virtsegs = vres_Find(virt, "SEGS");
virtlump_t* virtnodes = vres_Find(virt, "NODES");
if (!virtssectors)
I_Error("SSECTORS lump not found");
if (!virtsegs)
I_Error("SEGS lump not found");
if (!virtnodes)
I_Error("NODES lump not found");
numsubsectors = virtssectors->size / sizeof(mapsubsector_t);
numnodes = virtnodes->size / sizeof(mapnode_t);
numsegs = virtsegs->size / sizeof(mapseg_t);
@@ -3429,13 +3424,7 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local)
{
// check if someone tries to load maps locally lol
// do this here so we can skip loading the file anyways
int retmap = W_CheckAutoLoadContainsMap(wadfilename);
if (retmap == -1)
{
CONS_Alert(CONS_WARNING, "addilelocal: file %s was not found or not valid.\n", wadfilename);
return UINT16_MAX;
}
if (retmap > 0)
if (W_CheckAutoLoadContainsMap(wadfilename))
{
CONS_Alert(CONS_WARNING, "addilelocal: locally added file %s contains map data, this WILL cause crashes and desynchs! not added.\n", wadfilename);
return UINT16_MAX;
+3 -9
View File
@@ -1962,19 +1962,13 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (!dest)
return;
const angle_t ang = (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle;
const boolean dontstopmove = (line->flags & ML_EFFECT4) == ML_EFFECT4;
if (bot)
P_Teleport(bot, dest->x, dest->y, dest->z, ang, (line->flags & ML_BLOCKMONSTERS) == 0, dontstopmove);
P_Teleport(bot, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, (line->flags & ML_BLOCKMONSTERS) == 0, (line->flags & ML_EFFECT4) == ML_EFFECT4);
if (line->flags & ML_BLOCKMONSTERS)
{
P_Teleport(mo, dest->x, dest->y, dest->z, ang, false, dontstopmove);
}
P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, false, (line->flags & ML_EFFECT4) == ML_EFFECT4);
else
{
P_Teleport(mo, dest->x, dest->y, dest->z, ang, true, dontstopmove);
P_Teleport(mo, dest->x, dest->y, dest->z, (line->flags & ML_NOCLIMB) ? mo->angle : dest->angle, true, (line->flags & ML_EFFECT4) == ML_EFFECT4);
// Play the 'bowrwoosh!' sound
S_StartSound(dest, sfx_mixup);
}
+11 -17
View File
@@ -91,7 +91,7 @@ void P_InstaThrust(mobj_t *mo, angle_t angle, fixed_t move)
mo->momx = FixedMul(move, FINECOSINE(angle));
if (!twodmo(mo))
mo->momy = FixedMul(move, FINESINE(angle));
mo->momy = FixedMul(move,FINESINE(angle));
}
void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move)
@@ -4517,33 +4517,27 @@ static void DoABarrelRoll(player_t *player)
static void P_DoFunnyDance(player_t *player)
{
fixed_t bpm; // 140bpm ish
fixed_t work, ang, bounce; // hehe squishy
I_Assert(player != NULL);
I_Assert(!P_MobjWasRemoved(player->mo));
if (player->spectator)
if (player->spectator || !player->mo || player->kartstuff[k_respawn] || player->mo->salty.jump) // this looks jank as hell during hop
return;
// this looks jank as hell during hop or respawn
if (player->kartstuff[k_respawn] || player->salty.jump)
return;
player->squishdance.bounce = 0;
// bpm = FixedDiv((60*TICRATE)<<FRACBITS, FLOAT_TO_FIXED(mapmusic.bpm)); << maybe can get the tempo and beat detection lib to work for bpm autodetection
bpm = ((60*TICRATE) / (cv_squishdancespeed.value)) << FRACBITS;
bpm = FixedDiv((60*TICRATE)<<FRACBITS, FLOAT_TO_FIXED((float)cv_squishdancespeed.value));
work = (player->squishdance.time << FRACBITS) % bpm;
player->squishdance.work = (player->squishdance.time << FRACBITS) % bpm;
if (player->squishdance.time >= (FRACUNIT >> 1)) // prevent overflow jump - takes about 15 minutes
player->squishdance.time = (work >> FRACBITS);
player->squishdance.time = (player->squishdance.work >> FRACBITS);
work = FixedDiv(work*180, bpm);
player->squishdance.work = FixedDiv(player->squishdance.work*180, bpm);
ang = ((FixedAngle(work) >> ANGLETOFINESHIFT) & FINEMASK);
bounce = ((FINESINE(ang) - FRACUNIT/2) / 2);
player->squishdance.ang = ((FixedAngle(player->squishdance.work) >> ANGLETOFINESHIFT) & FINEMASK);
player->squishdance.bounce = ((FINESINE(player->squishdance.ang) - FRACUNIT/2) / 2);
player->mo->spritexscale -= bounce;
player->mo->spriteyscale += bounce;
player->mo->spritexscale -= player->squishdance.bounce;
player->mo->spriteyscale += player->squishdance.bounce;
player->squishdance.time++;
}
+1 -1
View File
@@ -6,7 +6,7 @@
// Copyright (C) 1996 by id Software, Inc.
// Copyright (C) 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
// Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
// Copyright (C) 2005, 2006 by Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
// Copyright (C) Copyright 2005, 2006 by Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
// Copyright (C) 2013 by James Haley, Stephen McGranahan, et al.
//
// This program is free software distributed under the
+38 -6
View File
@@ -61,6 +61,7 @@ fixed_t rw_distance = 0;
static INT32 rw_x, rw_stopx;
static angle_t rw_centerangle;
static fixed_t rw_offset;
static fixed_t rw_offset2; // for splats
static fixed_t rw_scale, rw_scalestep;
static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid;
static INT32 worldtop, worldbottom, worldhigh, worldlow;
@@ -263,7 +264,12 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3
else if (P_ApplyLightOffset(lightnum, frontsector))
lightnum += curline->lightOffset;
walllights = R_GetWallLight(lightnum);
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS - 1];
else
walllights = scalelight[lightnum];
}
if (frontsector->heightsec != -1)
@@ -365,7 +371,12 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3
lightnum = rlight->lightnum;
xwalllights = R_GetWallLight(lightnum);
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
@@ -813,7 +824,12 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf
else if (P_ApplyLightOffset(lightnum, frontsector))
lightnum += curline->lightOffset;
walllights = R_GetWallLight(lightnum);
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS-1];
else
walllights = scalelight[lightnum];
}
maskedtexturecol = drawseg->thicksidecol;
@@ -955,7 +971,12 @@ void R_RenderThickSideRange(drawseg_t *drawseg, INT32 x1, INT32 x2, ffloor_t *pf
lightnum = rlight->lightnum;
xwalllights = R_GetWallLight(lightnum);
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
@@ -1446,7 +1467,12 @@ static void R_RenderSegLoop(drawcolumndata_t* dc)
else if (P_ApplyLightOffset(lightnum, curline->frontsector))
lightnum += curline->lightOffset;
xwalllights = R_GetWallLight(lightnum);
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(rw_scale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
@@ -2525,6 +2551,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
rw_offset = -rw_offset;
/// don't use texture offset for splats
rw_offset2 = rw_offset + curline->offset;
rw_offset += sidedef->textureoffset + curline->offset;
rw_centerangle = ANGLE_90 + viewangle - rw_normalangle;
@@ -2537,7 +2564,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (P_ApplyLightOffset(lightnum, frontsector))
lightnum += curline->lightOffset;
walllights = R_GetWallLight(lightnum);
if (lightnum < 0)
walllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
walllights = scalelight[LIGHTLEVELS - 1];
else
walllights = scalelight[lightnum];
}
// if a floor / ceiling plane is on the wrong side
-5
View File
@@ -22,11 +22,6 @@ extern "C" {
#pragma interface
#endif
FUNCINLINE static ATTRINLINE lighttable_t** R_GetWallLight(INT32 llevel)
{
return scalelight[CLAMP(llevel, 0, LIGHTLEVELS-1)];
}
void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2);
void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor);
void R_StoreWallRange(INT32 start, INT32 stop);
+20 -5
View File
@@ -1062,7 +1062,12 @@ static void R_SplitSprite(vissprite_t *sprite)
{
INT32 lightnum = R_GetSoftLightlevel(*sector->lightlist[i].lightlevel);
spritelights = R_GetWallLight(lightnum);
if (lightnum < 0)
spritelights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
spritelights = scalelight[LIGHTLEVELS-1];
else
spritelights = scalelight[lightnum];
newsprite->extra_colormap = sector->lightlist[i].extra_colormap;
@@ -1740,7 +1745,12 @@ static void R_ProjectSprite(mobj_t *thing)
}
}
lights_array = R_GetWallLight(lightnum);
if (lightnum < 0)
lights_array = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
lights_array = scalelight[LIGHTLEVELS-1];
else
lights_array = scalelight[lightnum];
}
// store information in a vissprite
@@ -2077,11 +2087,16 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
if (!sec->numlights)
{
if (sec->heightsec == -1)
lightlevel = sec->lightlevel;
if (sec->heightsec == -1) lightlevel = sec->lightlevel;
lightnum = R_GetSoftLightlevel(lightlevel);
spritelights = R_GetWallLight(lightnum);
if (lightnum < 0)
spritelights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
spritelights = scalelight[LIGHTLEVELS-1];
else
spritelights = scalelight[lightnum];
}
// Handle all things in sector.
+3 -8
View File
@@ -233,25 +233,20 @@ if(${SDL2_FOUND})
-DHAVE_THREADS
)
if(SRB2_CONFIG_LTO AND NOT SRB2_CONFIG_DEBUGMODE AND NOT SRB2_CONFIG_ASAN AND NOT SRB2_CONFIG_UBSAN AND NOT SRB2_CONFIG_TSAN)
if(SRB2_CONFIG_LTO AND NOT SRB2_CONFIG_DEBUGMODE)
set_property(TARGET SRB2SDL2 PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
if(SRB2_CONFIG_ASAN)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=address -fno-omit-frame-pointer -fno-common)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=address)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=address)
endif()
if(SRB2_CONFIG_UBSAN)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=undefined -fno-omit-frame-pointer)
target_compile_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
endif()
if(SRB2_CONFIG_TSAN)
target_compile_options(SRB2SDL2 PRIVATE -O1 -fsanitize=thread -fno-omit-frame-pointer)
target_link_options(SRB2SDL2 PRIVATE -fsanitize=thread)
endif()
if(NOT SRB2_CONFIG_MUMBLE)
target_compile_options(SRB2SDL2 PRIVATE -DNOMUMBLE)
endif()
+66 -31
View File
@@ -97,9 +97,11 @@ static char vidModeName[33][32]; // allow 33 different modes
rendermode_t rendermode = render_none;
#ifdef HWRENDER
unsigned msaa = 0;
// Eee probably the way i organize it isn't best ><
// Just don't know where do i put declaration and "implementation"
unsigned msaa = 0;
boolean a2c = false;
#endif
static void KeyboardLayout_OnChange(void)
@@ -195,6 +197,10 @@ static INT32 custom_height = 0;
static SDL_bool Impl_CreateWindow(SDL_bool fullscreen);
static void Impl_SetWindowIcon(void);
#ifdef USE_FBO_OGL
boolean downsample = false;
#endif
static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
{
if (code >= SDL_SCANCODE_A && code <= SDL_SCANCODE_Z)
@@ -516,7 +522,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
{
I_CheckDesktopRes();
#ifdef USE_FBO_OGL
I_CheckDownSampleState(false);
I_DownSample();
#endif
windowmoved = SDL_FALSE;
}
@@ -1257,9 +1263,8 @@ static void I_CheckDesktopRes(void)
int currentDisplayIndex = -1;
SDL_DisplayMode curmode;
// just fallback to game res ig?
desktopwidth = vid.width;
desktopheight = vid.height;
desktopwidth = 0;
desktopheight = 0;
currentDisplayIndex = SDL_GetWindowDisplayIndex(window);
@@ -1269,7 +1274,7 @@ static void I_CheckDesktopRes(void)
return;
}
if (SDL_GetCurrentDisplayMode(currentDisplayIndex, &curmode) < 0)
if (SDL_GetDesktopDisplayMode(currentDisplayIndex, &curmode) != 0)
{
return;
}
@@ -1284,39 +1289,47 @@ boolean I_CheckNativeRes(void)
return (vid.width == desktopwidth && vid.height == desktopheight);
}
static boolean I_CheckAboveDesktopRes(INT32 width, INT32 height)
{
return (width > desktopwidth || height > desktopheight);
}
#ifdef USE_FBO_OGL
static boolean vid_downsampling = false;
boolean I_IsDownsampling(void)
void RefreshOGLSDLSurface(void)
{
return vid_downsampling;
if (rendermode == render_opengl)
OglSdlSurface(vid.width, vid.height);
}
void I_CheckDownSampleState(boolean forcerefresh)
void I_DownSample(void)
{
// no fbo support so we dont care
if (!supportFBO)
boolean needrefresh = false;
if (!cv_glframebuffer.value || !supportFBO || (cv_glscreentextures.value == 0)) // no sense to do this crap if we cant benefit from it
{
vid_downsampling = false;
downsample = false;
return;
}
// no sense to do this crap if we cant benefit from it
const boolean newdownsamplestate = cv_glframebuffer.value && (cv_glscreentextures.value == 2) && I_CheckAboveDesktopRes(vid.width, vid.height);
// state changed or fbo was toggled
if (vid_downsampling != newdownsamplestate || forcerefresh)
if (I_CheckNativeRes() && (downsample == true))
{
//printf("downsample changed from %d to %d\n", vid_downsampling, curdownsamplestate);
OglSdlSurface(vid.width, vid.height);
downsample = false;
RefreshOGLSDLSurface();
return;
}
vid_downsampling = newdownsamplestate;
if ((vid.width > desktopwidth) || (vid.height > desktopheight)) //check if current resolution is higher than current display resolution
{
downsample = true;
needrefresh = true;
}
else if (downsample == true)
{
downsample = false;
needrefresh = true;
}
if (needrefresh)
{
RefreshOGLSDLSurface();
needrefresh = false;
}
}
#endif
@@ -1346,11 +1359,10 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
}
// Reposition window only in windowed mode
const int windowpos = SDL_GetWindowDisplayIndex(window);
SDL_SetWindowSize(window, width, height);
SDL_SetWindowPosition(window,
SDL_WINDOWPOS_CENTERED_DISPLAY(windowpos),
SDL_WINDOWPOS_CENTERED_DISPLAY(windowpos)
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)),
SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window))
);
}
}
@@ -1372,7 +1384,7 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
{
I_CheckDesktopRes();
#ifdef USE_FBO_OGL
I_CheckDownSampleState(false);
I_DownSample();
#endif
OglSdlSurface(vid.width, vid.height);
}
@@ -1813,6 +1825,7 @@ void I_StartupGraphics(void)
rendermode = render_opengl;
msaa = 0; boolean msaa_set = false;
a2c = false; boolean a2c_set = false;
// MSAA antialiasing
if (M_CheckParm("-msaa") && M_IsNextParm())
@@ -1824,6 +1837,16 @@ void I_StartupGraphics(void)
}
}
if (M_CheckParm("-a2c"))
{
a2c = true;
a2c_set = true;
}
else if (M_CheckParm("-noa2c"))
{
a2c_set = true;
}
{
char line[16];
char * word;
@@ -1867,10 +1890,19 @@ void I_StartupGraphics(void)
}
else
{
CONS_Printf("Using last known MSAA value: %u\n", msaa);
CONS_Printf("Using last know MSAA value: %u\n", msaa);
}
}
}
if (!a2c_set)
{
if (fasticmp(word, "a2c"))
{
a2c = true;
CONS_Printf("Using a2c because it was specified to be used earlier\n");
}
}
}
fclose(file);
@@ -1905,6 +1937,9 @@ void I_StartupGraphics(void)
#ifdef HWRENDER
fprintf(file, "msaa %u\n", msaa);
if (a2c)
fputs("a2c\n", file);
#endif
fclose(file);
}
+10 -6
View File
@@ -65,7 +65,7 @@ PFNglGetString pglGetString;
#ifdef USE_FBO_OGL
boolean UseScreenFBO(void)
{
return (supportFBO && cv_glframebuffer.value && I_IsDownsampling() && (cv_glscreentextures.value == 2));
return (supportFBO && cv_glframebuffer.value && downsample);
}
#endif
@@ -203,9 +203,9 @@ boolean OglSdlSurface(INT32 w, INT32 h)
#ifdef USE_FBO_OGL
if (UseScreenFBO())
GL_FBO_Enable();
GL_Framebuffer_Enable();
else
GL_FBO_Disable();
GL_Framebuffer_Disable();
#endif
if (!first_init)
@@ -235,7 +235,9 @@ void OglSdlFinishUpdate(SDL_Window *window)
#ifdef USE_FBO_OGL
if (usefbo)
GL_FBO_BindMainFrameBuffer();
{
GL_Framebuffer_Unbind();
}
#endif
if (HWR_ShouldUsePaletteRendering())
@@ -253,7 +255,9 @@ void OglSdlFinishUpdate(SDL_Window *window)
#ifdef USE_FBO_OGL
if (usefbo)
GL_FBO_Enable();
{
GL_Framebuffer_Enable();
}
#endif
SDL_GL_SwapWindow(window);
@@ -264,7 +268,7 @@ void OglSdlFinishUpdate(SDL_Window *window)
// effects that want to take the old screen can do so after this
// well we dont need it on native res it seems
#ifdef USE_FBO_OGL
if (!usefbo && (!I_CheckNativeRes() || WipeInAction))
if ((!I_CheckNativeRes() && !usefbo) || WipeInAction)
#else
if (!I_CheckNativeRes() || WipeInAction)
#endif
+21
View File
@@ -804,6 +804,27 @@ void* Z_LevelPoolMalloc(size_t size)
return p;
}
boolean Z_IsMobjValid2(void *p, const char *file, INT32 line)
{
//(void)file;
//(void)line;
// mobj was removed
// no need to worry here
if (p == NULL)
return false;
// mobjs reside in the large pool
if (!g_level_large_pool.ptrcheck(p))
{
//I_Error("invalid mobj! at %s:%d", file, line);
CONS_Alert(CONS_ERROR, "invalid mobj! at %s:%d", file, line);
return false;
}
return true;
}
void* Z_LevelPoolCalloc(size_t size)
{
void* p = Z_LevelPoolMalloc(size);
+2
View File
@@ -173,6 +173,8 @@ char *Z_StrDup(const char *in);
size_t Z_LevelPoolUsage(void);
void *Z_LevelPoolMalloc(size_t size);
void *Z_LevelPoolCalloc(size_t size);
#define Z_IsMobjValid(p) Z_IsMobjValid2(p, __FILE__, __LINE__)
boolean Z_IsMobjValid2(void *p, const char *file, INT32 line);
void Z_LevelPoolFree(void *p, size_t size);
// for use with CLEANUP macro