Compare commits

..
Author SHA1 Message Date
alufolie91 3f68b0f8c1 OpenGL: prefer GL_RGBA for water screen copy
as per recommended https://wikis.khronos.org/opengl/Common_Mistakes
2026-10-01 19:30:35 +02:00
alufolie91 938c95c80d Merge branch 'Saturn-Next' into waterrefract 2026-08-23 03:30:14 +02:00
alufolie91 1552b1808f "about" 2026-08-21 16:51:04 +02:00
alufolie91 fd349e2b37 netsync mobj pmomz in non vanilla compat builds
may help with some join desynchs
2026-08-18 17:39:19 +02:00
alufolie91 0cf1cabcc2 basic 32 player support
can just be enabled per MAXPLAYERS define in doomdef
this will also auto undefine COMPAT_VANILLA
no support for tab rankings or intermission rankings at all yet
will port those over eventually from saturn 32p or blankart and clean stuff up
please note this may have bugs since not everything is ported over yet
2026-08-18 17:39:19 +02:00
alufolie91 bcbe765b9d fix potential buffer underflow in portal handling
P_FindSpecialLineFromTag may return -1 in some cases
2026-08-17 19:19:51 +02:00
alufolie91 eca3effb3b raise version to v10
was originally be 9.3 but this update is too massive to be a minor version update
2026-08-17 18:47:42 +02:00
Gustaf Alhäll f1380a276e Fix buffer overflow when running map scripts 2026-08-17 18:43:08 +02:00
James R 8ffeab1646 Reset wait period for COM_BufInsertText 2026-08-17 16:39:27 +02:00
alufolie91 2eb175c356 few more smaller code cleanups 2026-08-17 16:39:23 +02:00
alufolie91 4e606fc7de fix indentation 2026-08-10 15:50:35 +02:00
Gustaf Alhäll c5116dea1a Add support for OpenBSD 2026-08-10 15:50:32 +02:00
alufolie91 924f9c2151 put directory changing and getting stuff into functions
from https://gitlab.com/kart-krew-dev/ring-racers/-/commit/7ef40f5d743bf6bf251e2edc89cda23e8fb36ee5

changed a bit so windows also can print the "warning" on failure
2026-08-10 15:38:31 +02:00
alufolie91 e0fa53e4df demonames apparently should write one less character
better keep it like this
2026-08-10 15:33:40 +02:00
alufolie91 eeb7d48a6f one more snprintf replacement for next branch 2026-08-09 17:51:39 +02:00
alufolie91 df291710d8 replace a few more length magic numbers with sizeof
just to be sure really
2026-08-09 17:49:34 +02:00
alufolie91 16577877d3 replace all sprintf with snprintf
some of this was taken from https://gitlab.com/kart-krew-dev/ring-racers/-/commit/59f23dfa181327ed5c00f55688840d39e3583569 so thx!
should fix apple clang warnings and is alot safer to have all this crap be bounded
theres prob alot more other stuff, and id love to eventually replace all the strcpy family functions with snprintf and equivalent
2026-08-09 17:49:31 +02:00
alufolie91 309d459a70 fix apple clang warning for music test
define this as constant otherwise compiler may treat the array as being variable in size for some reason
2026-08-09 15:00:52 +02:00
alufolie91 e1430f7bc7 replace magic number with sizeof 2026-08-08 19:07:56 +02:00
alufolie91 bf70beb88a cleanup SV_SendServerInfo a little
mostly just make it more readable by using ptr
2026-08-08 19:03:31 +02:00
alufolie91 a951622f6a ensure serverinfo "application" is null terminated
not strictly needed but better be safe than sorry
2026-08-08 19:00:13 +02:00
alufolie91 d7db0d68dc ensure serverinfo mapname is null terminated
forgor back then
2026-08-08 18:53:55 +02:00
alufolie91 2b9224cc3f forgor to update player names comment 2026-08-08 18:09:45 +02:00
alufolie91 0a750cd3bc cleanup gl shadow checks
just move em into the function to be less ugly
2026-08-08 17:38:20 +02:00
alufolie91 0e8a32612f move player_name init to D_RegisterServerCommands
runs before registering client commands and is for everything server + client needs
2026-08-08 17:31:27 +02:00
Monster Iestyn 3c6882203b Initialise player_names[] in D_RegisterClientCommands such that we don't need to have to manually update it if MAXPLAYERS ever changed 2026-08-08 17:31:23 +02:00
alufolie91 0464a8b0c7 attempt to mitigate "palette" cvar allowing random lumps to be used as palette
if theres a proper way to check for actual palettes pls tell me thx
2026-08-07 20:14:48 +02:00
alufolie91 599eda96aa fix M_ScrollString not null terminating its output
this caused music test to have non terminated strings
2026-08-07 19:36:51 +02:00
alufolie91 421d735052 fix compiler complains when compiling with valgrind support 2026-08-06 22:16:50 +02:00
alufolie91 73bc64f9da fix clamp assert in HWR_SplitWall
idk man it really hates if lo > hi apparently lol
2026-08-06 22:16:48 +02:00
alufolie91 5d807d65e5 smol style fix
less confusing
2026-08-06 17:43:15 +02:00
alufolie91 88d86a6e60 fix NOMUMBLE compile
idk how and why this breaks, but I_OutputMsg is in  doomdef anyways for god knows why
2026-08-06 17:05:09 +02:00
alufolie91 b2cdbaae60 fix protocol register thingie 2026-08-06 16:58:07 +02:00
alufolie91 9160431556 fix compile for android bionic c lib 2026-08-06 16:58:01 +02:00
alufolie91 2f9a400cf3 cmake flag for mumble
stimky
2026-08-06 16:51:51 +02:00
alufolie91 c39073dd9e fix arm compile
idk why i added this, if this is ever needed for whatever pls yell at me
2026-08-06 15:09:48 +02:00
alufolie91 f03692b840 delet duped MobjThinker check 2026-08-05 22:50:11 +02:00
MIDIMan 617e8fdd55 Manually set NetVars's hook_type
Also adds a 2.3 TODO comment for MF_AMBIENT
2026-08-05 22:49:53 +02:00
alufolie91 d5252bd3b3 fix an oopsie in p_mobj.c
prob did that while sleep deprived, P_WeaponOrPanel includes a few more things than intended to be there
doubt we even use any of those, but i dont want to cause any potential issues agaion
2026-07-28 20:49:23 +02:00
alufolie91 94f46c3ce6 also prevent "local" pushable mobjs from executing linedef actions
missed when i did the other, pushables have a seperate executor special
2026-07-25 09:24:59 +02:00
alufolie91 c3e709231d Merge branch 'luaprofile' into Saturn-Next 2026-07-24 16:18:59 +02:00
alufolie91 7878e01e3f update copyrights for "core" folder 2026-07-24 16:15:56 +02:00
alufolie91 4631844c9f revert removing the slopelanding dupe
dont think this would cause any issues at all, but i dont feel like maybe causing some dumbass edge cases anywhere really
can test this further after v10 release since its already taking ages
2026-07-24 16:07:28 +02:00
alufolie91 0c440d240c can pass char to this now
no need to reconvert this stuff from const char to std::string and back to const char really lol
2026-07-24 15:54:50 +02:00
alufolie91 5c7be85977 fix cmake
.ch..........
2026-07-24 15:50:35 +02:00
alufolie91 c401926c0b fix lua hook profiler drawing out of screen bounds in some cases
this omits alot of hooks in the profiler, tho not sure if anyone should even care about those back in the list
maybe just have it have multiple pages like perfstats, or better just integrate it into perfstats......
2026-07-24 15:48:57 +02:00
alufolie91 e0e8be8d46 perfstats thinkframe maxpage fix from blan
+ also yoink the ps types to get rid of magic numbers
just prevents the cvar being set to a page that does not exist
2026-07-24 15:47:44 +02:00
alufolie91 957d3f7229 delet fmt for lua hook profiler
i dont want another stinky library
this would just be an arsepain to include in windoze builds

TODO: make this drawer less of a mess, maybe integrate into perfstats instead?
2026-07-24 15:31:16 +02:00
alufolie91 7e47b9b6ba fix crash in K_drawKartMinimapHead if player mobj was removed 2026-07-24 07:36:47 +02:00
romoney5 6e91e00289 Ignore scenery thinker for player objects
Prevents Lua from being able to remove player objects using MF_SCENERY
and causing potential crashes
2026-07-24 07:36:43 +02:00
alufolie91 a539f38e72 add more safety checks to some maploading stuff
+ rename things to make more sense
2026-07-21 20:33:46 +02:00
alufolie91 4f21d8f983 dont apply lua rumble during replay playback
same as non lua rumble
2026-07-21 16:05:11 +02:00
alufolie91 dfc7b5482e Merge branch 'Saturn-Next' into waterrefract 2026-07-20 16:45:18 +02:00
alufolie91 d258c920de Merge remote-tracking branch 'origin/Saturn-Next' into waterrefract 2026-07-20 11:47:31 +02:00
alufolie91 b3eac23977 dont draw refraction planes in wireframe mode
idk but this prob just fucks shit up
2026-07-17 22:43:31 +02:00
alufolie91 a114dd840b Merge branch 'Saturn-Next' into waterrefract 2026-07-17 22:43:28 +02:00
alufolie91 87fa339c8d tweak ripple and refraction shaders
this much much more closely resembles the software effect
i manually tweaked this until it looked very similar
its still not quite perfect probably, but in many cases its a close match
2026-07-17 08:39:26 +02:00
alufolie91 afb5b717fe smol change to GL_DrawWaterPolygon
this doesent need anything, its basically just a blank polygon, so can save some work and also pass less stuff to this
2026-07-16 20:20:45 +02:00
alufolie91 1a7dc425d2 remove horizonline handling for refraction planes
forgot those wont work with fofs anyways
still need to look into that sometime
but thisll save some perf
2026-07-16 18:31:45 +02:00
alufolie91 038e8f0864 clean up the refraction shader a bit
most stuff wasnt needed, forgot to remove it earlier
2026-07-16 18:18:36 +02:00
alufolie91 8ac506bf35 change how water refraction is handled
split it into its own pass
we will draw "refraction planes" before drawing anything translucent
this way we wont cause any draw order issues or anything like that
this is also a bit faster and more sane than the other approach
only caveat: translucent stuff behind water planes is unaffected by refraction
but better than it was before, and sure better than trying to copy the screen per plane or shit like that lol
like this, this should be mostly feasible to actually use, the skybox water stuff kinda was a non issue since i noticed even just normal water does not draw over the map geometry (must have misremembered that part since software does do that), but still might be worth looking into at some point
2026-07-16 17:57:55 +02:00
alufolie91 6cf2561dd3 dedupe GL_DrawWaterPolygon 2026-07-16 17:57:52 +02:00
alufolie91 3e459d4a21 WIP: OpenGL water refraction
tries to replicate the effect from software renderer
this is quite a mess, but finally feel like pushing this since i finally figured out the depth testing stuff
this still has some issues:
-map geometry in front of skybox water will just draw over it completely (not super sure how to fix this other than deferring water rendering after rendering both skybox and normal scene)
-translucent geometry is not included in refraction (and may draw in front of it?), software also suffers from this in certain cases, i just hope its not that visible

this really needs a cleanup at some point
and due to how this is setup for floor and ceiling planes this also costs quite a lot of gpu time (atleast on the cpu side this costs barely anything)
2026-07-16 17:57:46 +02:00
alufolie91 38a248193e make lua hook profiler kinda work
very scuffed up since we dont have the srb2::Draw lib
so it may display stuff out of screen bounds
i also rather not use fmt here but va since i dont want another dependency
needs to be fixed up sometime
2026-07-01 18:15:38 +02:00
James R 934f2d347c Add basic profiling for Lua hooks (except HUD hooks)
- Add lua_profile cheat: calculate average time spent in
  hooks over a period
- Show hook times in a sorted table, along with lump name,
  script line number and hook type
- Show cumulative time spent in game logic hooks and
  percentage of overhead to game logic
2026-07-01 18:13:51 +02:00
83 changed files with 1621 additions and 767 deletions

No files matched your search

+5
View File
@@ -247,6 +247,9 @@ set(SRB2_CONFIG_ASAN OFF CACHE BOOL
set(SRB2_CONFIG_UBSAN OFF CACHE BOOL
"Compile with UndefinedBehaviorSanitizer (libubsan).")
set(SRB2_CONFIG_MUMBLE ON CACHE BOOL
"Enable Mumble support")
set(SRB2_CONFIG_SATURNPAK ON CACHE BOOL
"Enable Saturn specific special packet. Required for using the newer resynch system")
set(SRB2_CONFIG_SATURNJOIN ON CACHE BOOL
@@ -275,6 +278,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
lua_hooklib.c
lua_hudlib.c
lua_hudlib_drawlist.c
lua_profile.cpp
lua_infolib.c
lua_maplib.c
lua_mathlib.c
@@ -290,6 +294,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
lua_hook.h
lua_hud.h
lua_hudlib_drawlist.h
lua_profile.h
lua_libs.h
lua_script.h
lua_udatalib.h
-4
View File
@@ -246,10 +246,6 @@ ifdef STATIC
libs+=-static
endif
ifneq (,$(filter $(CC) $(CXX),gcc g++))
opts+=-mno-ms-bitfields
endif
# build with profiling information
ifdef PROFILEMODE
opts+=-pg
+1 -1
View File
@@ -86,7 +86,7 @@ ifdef VALGRIND
VALGRIND_PKGCONFIG?=valgrind
VALGRIND_LDFLAGS=
$(eval $(call Use_pkg_config,VALGRIND))
ZDEBUG=1
#ZDEBUG=1 we enable this by default
opts+=-DHAVE_VALGRIND
endif
+1
View File
@@ -99,3 +99,4 @@ lua_skinlib.c
lua_thinkerlib.c
lua_udatalib.c
lua_glib.c
lua_profile.cpp
+1 -1
View File
@@ -143,7 +143,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
}
case 'p': {
char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
sprintf(buff, "%p", va_arg(argp, void *));
snprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
pushstr(L, buff);
break;
}
+6 -6
View File
@@ -776,23 +776,23 @@ static int str_format (lua_State *L) {
strfrmt = scanformat(L, strfrmt, form);
switch (*strfrmt++) {
case 'c': {
sprintf(buff, form, (int)luaL_checknumber(L, arg));
snprintf(buff, sizeof(buff), form, (int)luaL_checknumber(L, arg));
break;
}
case 'd': case 'i': {
addintlen(form);
sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
snprintf(buff, sizeof(buff), form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
case 'o': case 'u': case 'x': case 'X': {
addintlen(form);
sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
snprintf(buff, sizeof(buff), form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
break;
}
case 'e': case 'E': case 'f':
case 'g': case 'G': {
lua_Number n = luaL_checknumber(L, arg);
sprintf(buff, form, (double)n);
lua_Number n = luaL_checknumber(L, arg);
snprintf(buff, sizeof(buff), form, (double)n);
break;
}
case 'q': {
@@ -810,7 +810,7 @@ static int str_format (lua_State *L) {
continue; /* skip the `addsize' at the end */
}
else {
sprintf(buff, form, s);
snprintf(buff, sizeof(buff), form, s);
break;
}
}
+1 -1
View File
@@ -536,7 +536,7 @@
#define LUA_NUMBER_SCAN "%d"
#define LUA_NUMBER_FMT "%d"
#endif
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#define lua_number2str(s,n) snprintf((s), LUAI_MAXNUMBER2STR, LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 12 /* 10 digits, sign, and \0 */
#define lua_str2number(s,p) ({ \
long nmr = strtol((s), (p), 10); \
+42 -15
View File
@@ -113,18 +113,29 @@ static vsbuf_t com_text; // variable sized buffer
* \param ptext The text to add.
* \sa COM_BufInsertText
*/
void COM_BufAddText(const char *ptext)
void COM_BufAddTextEx(const char *ptext, size_t plen)
{
size_t l;
char *text;
l = strlen(ptext);
if (plen == 0)
plen = strlen(ptext);
text = Z_Malloc(sizeof(char) * (plen+1), PU_STATIC, NULL);
memcpy(text, ptext, plen);
text[plen] = '\0';
l = strlen(text);
if (com_text.cursize + l >= com_text.maxsize)
{
CONS_Alert(CONS_WARNING, M_GetText("Command buffer full!\n"));
return;
}
VS_Write(&com_text, ptext, l);
VS_Write(&com_text, text, l);
Z_Free(text);
}
/** Adds command text and executes it immediately.
@@ -132,8 +143,10 @@ void COM_BufAddText(const char *ptext)
* \param ptext The text to execute. A newline is automatically added.
* \sa COM_BufAddText
*/
void COM_BufInsertText(const char *ptext)
void COM_BufInsertTextEx(const char *ptext, size_t plen)
{
const INT32 old_wait = com_wait;
char *temp = NULL;
size_t templen;
@@ -145,10 +158,14 @@ void COM_BufInsertText(const char *ptext)
VS_Clear(&com_text);
}
com_wait = 0;
// add the entire text of the file (or alias)
COM_BufAddText(ptext);
COM_BufAddTextEx(ptext, plen);
COM_BufExecute(); // do it right away
com_wait += old_wait;
// add the copied off data
if (templen)
{
@@ -159,8 +176,7 @@ void COM_BufInsertText(const char *ptext)
/** Progress the wait timer and flush waiting console commands when ready.
*/
void
COM_BufTicker(void)
void COM_BufTicker(void)
{
if (com_wait)
{
@@ -1596,7 +1612,9 @@ void CV_SaveNetVars(UINT8 **p, boolean isdemorecording)
// send only changed cvars ...
// the client will reset all netvars to default before loading
WRITEUINT16(*p, 0x0000);
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) || (isdemorecording && cvar->netid == cv_numlaps.netid))
{
WRITEUINT16(*p, cvar->netid);
@@ -1614,7 +1632,7 @@ void CV_SaveNetVars(UINT8 **p, boolean isdemorecording)
else
{
char buf[9];
sprintf(buf, "%d", mapheaderinfo[gamemap - 1]->numlaps);
snprintf(buf, sizeof(buf), "%d", mapheaderinfo[gamemap - 1]->numlaps);
WRITESTRING(*p, buf);
}
}
@@ -1626,6 +1644,8 @@ void CV_SaveNetVars(UINT8 **p, boolean isdemorecording)
WRITEUINT8(*p, false);
++count;
}
}
WRITEUINT16(count_p, count);
}
@@ -1782,8 +1802,7 @@ void CV_StealthSet(consvar_t *var, const char *value)
void CV_StealthSetValue(consvar_t *var, INT32 value)
{
char val[32];
sprintf(val, "%d", value);
snprintf(val, sizeof(val), "%d", value);
CV_SetCVar(var, val, true);
}
@@ -1803,8 +1822,7 @@ void CV_Set(consvar_t *var, const char *value)
void CV_SetValue(consvar_t *var, INT32 value)
{
char val[32];
sprintf(val, "%d", value);
snprintf(val, sizeof(val), "%d", value);
CV_SetCVar(var, val, false);
}
@@ -2202,6 +2220,7 @@ void CV_SaveVariables(FILE *f)
consvar_t *cvar;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->flags & CV_SAVE)
{
char stringtowrite[MAXTEXTCMD+1];
@@ -2210,15 +2229,23 @@ void CV_SaveVariables(FILE *f)
if (fastcmp(cvar->string, "MAX") || fastcmp(cvar->string, "MIN"))
{
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FixedToFloat(cvar->value));
{
snprintf(stringtowrite, sizeof(stringtowrite), "%f", FixedToFloat(cvar->value));
}
else
sprintf(stringtowrite, "%d", cvar->value);
{
snprintf(stringtowrite, sizeof(stringtowrite), "%d", cvar->value);
}
}
else
strcpy(stringtowrite, cvar->string);
{
strncpy(stringtowrite, cvar->string, sizeof(stringtowrite)-1);
stringtowrite[sizeof(stringtowrite)-1] = '\0';
}
fprintf(f, "%s \"%s\"\n", cvar->name, stringtowrite);
}
}
}
//============================================================================
+4 -2
View File
@@ -52,10 +52,12 @@ size_t COM_FirstOption(void);
const char *COM_CompleteCommand(const char *partial, INT32 skips);
// insert at queu (at end of other command)
void COM_BufAddText(const char *btext);
#define COM_BufAddText(s) COM_BufAddTextEx(s, 0)
void COM_BufAddTextEx(const char *ptext, size_t plen);
// insert in head (before other command)
void COM_BufInsertText(const char *btext);
#define COM_BufInsertText(s) COM_BufInsertTextEx(s, 0)
void COM_BufInsertTextEx(const char *ptext, size_t plen);
// don't bother inserting, just do immediately
void COM_ImmedExecute(const char *ptext);
+3 -3
View File
@@ -1,7 +1,7 @@
// BLANKART
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
+3 -3
View File
@@ -1,7 +1,7 @@
// SONIC ROBO BLAST 2 KART
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
+3 -3
View File
@@ -1,7 +1,7 @@
// SONIC ROBO BLAST 2 KART
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
+3 -3
View File
@@ -1,7 +1,7 @@
// BLANKART
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
+3 -3
View File
@@ -1,7 +1,7 @@
// SONIC ROBO BLAST 2 KART
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Ronald "Eidolon" Kinard
// Copyright (C) 2024 by Kart Krew
// Copyright (C) 2025 by Ronald "Eidolon" Kinard
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
+51 -45
View File
@@ -1629,8 +1629,8 @@ static boolean CL_SendJoin(void)
netbuffer->u.clientcfg.packetversion = PACKETVERSION;
netbuffer->u.clientcfg.version = VERSION;
netbuffer->u.clientcfg.subversion = SUBVERSION;
strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION,
sizeof(netbuffer->u.clientcfg.application));
strncpy(netbuffer->u.clientcfg.application, SRB2APPLICATION, sizeof(netbuffer->u.clientcfg.application)-1);
netbuffer->u.clientcfg.application[sizeof(netbuffer->u.clientcfg.application)-1] = '\0';
#ifdef SATURNJOIN
netbuffer->u.clientcfg.issaturn = ISSATURN;
#endif
@@ -1655,88 +1655,91 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
serverinfo_pak *serverinfo = &netbuffer->u.serverinfo;
netbuffer->packettype = PT_SERVERINFO;
netbuffer->u.serverinfo._255 = 255;
netbuffer->u.serverinfo.packetversion = PACKETVERSION;
netbuffer->u.serverinfo.version = VERSION;
netbuffer->u.serverinfo.subversion = SUBVERSION;
strncpy(netbuffer->u.serverinfo.application, SRB2APPLICATION,
sizeof netbuffer->u.serverinfo.application);
serverinfo->_255 = 255;
serverinfo->packetversion = PACKETVERSION;
serverinfo->version = VERSION;
serverinfo->subversion = SUBVERSION;
strncpy(serverinfo->application, SRB2APPLICATION, sizeof(serverinfo->application)-1);
serverinfo->application[sizeof(serverinfo->application)-1] = '\0';
// return back the time value so client can compute their ping
netbuffer->u.serverinfo.time = (tic_t)LONG(servertime);
netbuffer->u.serverinfo.leveltime = (tic_t)LONG(leveltime);
serverinfo->time = (tic_t)LONG(servertime);
serverinfo->leveltime = (tic_t)LONG(leveltime);
// force 1 player
if (UseFakeSeed())
netbuffer->u.serverinfo.numberofplayer = (UINT8)1;
serverinfo->numberofplayer = (UINT8)1;
else
netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers();
serverinfo->numberofplayer = (UINT8)D_NumPlayers();
netbuffer->u.serverinfo.maxplayer = (UINT8)(min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxplayers.value));
serverinfo->maxplayer = (UINT8)(min((dedicated ? MAXPLAYERS-1 : MAXPLAYERS), cv_maxplayers.value));
// SRB2Kart: Vanilla's gametype constants for MS support
netbuffer->u.serverinfo.gametype = (UINT8)((gt == GT_MATCH) ? VANILLA_GT_MATCH : VANILLA_GT_RACE);
serverinfo->gametype = (UINT8)((gt == GT_MATCH) ? VANILLA_GT_MATCH : VANILLA_GT_RACE);
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
serverinfo->modifiedgame = (UINT8)modifiedgame;
serverinfo->cheatsenabled = CV_CheatsEnabled();
netbuffer->u.serverinfo.kartvars = (UINT8) (
serverinfo->kartvars = (UINT8) (
(cv_kartspeed.value & SV_SPEEDMASK) |
(dedicated ? SV_DEDICATED : 0)
);
CopyCaretColors(netbuffer->u.serverinfo.servername, cv_servername.string,
MAXSERVERNAME);
strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), sizeof(netbuffer->u.serverinfo.mapname)-1);
CopyCaretColors(serverinfo->servername, cv_servername.string, MAXSERVERNAME);
memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, sizeof(netbuffer->u.serverinfo.mapmd5));
strncpy(serverinfo->mapname, G_BuildMapName(gamemap), sizeof(serverinfo->mapname)-1);
serverinfo->mapname[sizeof(serverinfo->mapname)-1] = '\0';
netbuffer->u.serverinfo.iszone = 0;
memcpy(serverinfo->mapmd5, mapmd5, sizeof(serverinfo->mapmd5));
memset(netbuffer->u.serverinfo.maptitle, 0, sizeof(netbuffer->u.serverinfo.maptitle));
memset(netbuffer->u.serverinfo.httpsource, 0, MAX_MIRROR_LENGTH);
serverinfo->iszone = 0;
memset(serverinfo->maptitle, 0, sizeof(serverinfo->maptitle));
memset(serverinfo->httpsource, 0, MAX_MIRROR_LENGTH);
if (!(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU) && mapheaderinfo[gamemap-1]->lvlttl[0])
{
strncpy(netbuffer->u.serverinfo.maptitle, mapheaderinfo[gamemap-1]->lvlttl, sizeof(netbuffer->u.serverinfo.maptitle)-1);
strncpy(serverinfo->maptitle, mapheaderinfo[gamemap-1]->lvlttl, sizeof(serverinfo->maptitle)-1);
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
{
if (mapheaderinfo[gamemap-1]->zonttl[0])
{
strncat(netbuffer->u.serverinfo.maptitle, " ", sizeof(netbuffer->u.serverinfo.maptitle)-1);
strncat(netbuffer->u.serverinfo.maptitle, mapheaderinfo[gamemap-1]->zonttl,
sizeof(netbuffer->u.serverinfo.maptitle)-1);
strncat(serverinfo->maptitle, " ", sizeof(serverinfo->maptitle)-1);
strncat(serverinfo->maptitle, mapheaderinfo[gamemap-1]->zonttl, sizeof(serverinfo->maptitle)-1);
}
else
{
netbuffer->u.serverinfo.iszone = 1; // ms and clients will append this themselves
serverinfo->iszone = 1; // ms and clients will append this themselves
}
}
if (mapheaderinfo[gamemap-1]->actnum[0])
{
strncat(netbuffer->u.serverinfo.maptitle, " ", sizeof(netbuffer->u.serverinfo.maptitle)-1);
strncat(netbuffer->u.serverinfo.maptitle, mapheaderinfo[gamemap-1]->actnum,
sizeof(netbuffer->u.serverinfo.maptitle)-1);
strncat(serverinfo->maptitle, " ", sizeof(serverinfo->maptitle)-1);
strncat(serverinfo->maptitle, mapheaderinfo[gamemap-1]->actnum, sizeof(serverinfo->maptitle)-1);
}
}
else
strncpy(netbuffer->u.serverinfo.maptitle, "Unknown", 33);
{
strncpy(serverinfo->maptitle, "Unknown", sizeof(serverinfo->maptitle)-1);
}
netbuffer->u.serverinfo.maptitle[32] = '\0';
serverinfo->maptitle[sizeof(serverinfo->maptitle)-1] = '\0';
netbuffer->u.serverinfo.actnum = 0; //mapheaderinfo[gamemap-1]->actnum
serverinfo->actnum = 0; //mapheaderinfo[gamemap-1]->actnum
mirror_length = strlen(httpurl);
if (mirror_length > MAX_MIRROR_LENGTH)
mirror_length = MAX_MIRROR_LENGTH;
if (snprintf(netbuffer->u.serverinfo.httpsource, mirror_length+1, "%s", httpurl) < 0)
if (snprintf(serverinfo->httpsource, mirror_length+1, "%s", httpurl) < 0)
// If there's an encoding error, send nothing, we accept that the above may be truncated
strncpy(netbuffer->u.serverinfo.httpsource, "", mirror_length);
strncpy(serverinfo->httpsource, "", mirror_length);
netbuffer->u.serverinfo.httpsource[MAX_MIRROR_LENGTH-1] = '\0';
serverinfo->httpsource[MAX_MIRROR_LENGTH-1] = '\0';
p = PutFileNeeded(0);
@@ -2094,7 +2097,7 @@ static void SV_SavedGame(void)
if (!cv_dumpconsistency.value)
return;
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
snprintf(tmpsave, sizeof(tmpsave), "%s" PATHSEP TMPSAVENAME, srb2home);
// first save it in a malloced buffer
save.p = save.buffer = (UINT8 *)Z_Malloc(SAVEGAMESIZE, PU_STATIC, NULL);
@@ -2132,7 +2135,7 @@ static void CL_LoadReceivedSavegame(boolean reloading)
size_t length, decompressedlen;
char tmpsave[264];
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
snprintf(tmpsave, sizeof(tmpsave), "%s" PATHSEP TMPSAVENAME, srb2home);
length = FIL_ReadFile(tmpsave, &save.buffer);
@@ -2211,7 +2214,7 @@ static void CL_ReloadReceivedSavegame(void)
for (i = 0; i < MAXPLAYERS; i++)
{
LUA_InvalidatePlayer(&players[i]);
sprintf(player_names[i], "Player %d", i + 1);
snprintf(player_names[i], MAXPLAYERNAME+1, "Player %d", i + 1);
}
CL_LoadReceivedSavegame(true);
@@ -2947,7 +2950,7 @@ static void CL_ConnectToServer(void)
tic_t asksent;
char tmpsave[264];
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
snprintf(tmpsave, sizeof(tmpsave), "%s" PATHSEP TMPSAVENAME, srb2home);
filedownload.current = -1;
cl_mode = CL_SEARCHING;
@@ -3510,7 +3513,7 @@ void CL_RemovePlayer(INT32 playernum, INT32 reason)
player_muted[playernum] = false;
// Reset the name
sprintf(player_names[playernum], "Player %d", playernum+1);
snprintf(player_names[playernum], MAXPLAYERNAME+1, "Player %d", playernum+1);
player_name_changes[playernum] = 0;
@@ -4472,7 +4475,7 @@ void SV_ResetServer(void)
for (i = 0; i < MAXPLAYERS; i++)
{
LUA_InvalidatePlayer(&players[i]);
sprintf(player_names[i], "Player %d", i + 1);
snprintf(player_names[i], MAXPLAYERNAME+1, "Player %d", i + 1);
}
memset(player_name_changes, 0, sizeof(player_name_changes));
@@ -5531,7 +5534,7 @@ static void PT_WillResendGamestate(void)
CONS_Printf(M_GetText("Reloading game state...\n"));
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
snprintf(tmpsave, sizeof(tmpsave), "%s" PATHSEP TMPSAVENAME, srb2home);
// Don't get a corrupt savegame error because tmpsave already exists
if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1)
@@ -6873,7 +6876,10 @@ boolean TryRunTics(tic_t realtics)
DEBFILE(va("============ Running tic %d (local %d)\n", gametic, leveltime));
if (update_stats)
{
ps_prevtictime = ps_tictime;
PS_START_TIMING(ps_tictime);
}
G_Ticker((gametic % NEWTICRATERATIO) == 0);
ExtraDataTicker();
+7 -1
View File
@@ -79,6 +79,7 @@
#include "core/memory.h"
#include "lua_script.h"
#include "lua_profile.h"
/* Manually defined asset hashes for non-CMake builds
* Last updated 2015 / 05 / 03 - SRB2 v2.1.15 - srb2.srb
@@ -644,6 +645,11 @@ static boolean D_Display(void)
CON_Drawer(); // Ha, i LIED!
if (cv_lua_profile.value > 0)
{
LUA_RenderTimers();
}
PS_START_TIMING(ps_swaptime);
I_FinishUpdate(); // page flip or blit buffer
PS_STOP_TIMING(ps_swaptime);
@@ -1239,7 +1245,7 @@ static void IdentifyVersion(void)
#endif
char tempsrb2path[256] = ".";
if (getcwd(tempsrb2path, 256) == NULL)
if (I_GetCwd(tempsrb2path, 256) == NULL)
strcpy(tempsrb2path, ".");
// get the current directory (possible problem on NT with "." as current dir)
+3 -1
View File
@@ -1315,7 +1315,9 @@ boolean D_CheckNetGame(void)
while (!debugfile && k < MAXPLAYERS)
{
k++;
sprintf(filename, "debug%d.txt", k);
snprintf(filename, sizeof(filename), "debug%d.txt", k);
debugfile = fopen(va("%s" PATHSEP "%s", srb2home, filename), "w");
}
+26 -10
View File
@@ -47,6 +47,7 @@
#include "z_zone.h"
#include "lua_script.h"
#include "lua_hook.h"
#include "lua_profile.h"
#include "m_cond.h"
#include "m_anigif.h"
#include "k_kart.h" // SRB2kart
@@ -506,6 +507,9 @@ static CV_PossibleValue_t ps_descriptor_cons_t[] = {
{1, "Average"}, {2, "SD"}, {3, "Minimum"}, {4, "Maximum"}, {0, NULL}};
consvar_t cv_ps_descriptor = {"ps_descriptor", "Average", 0, ps_descriptor_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
//consvar_t cv_lua_profile = {"lua_profile", "0").values(CV_Unsigned).onchange(lua_profile_OnChange).description("Show hook timings over an average of N tics");
consvar_t cv_lua_profile = {"lua_profile", "0", CV_CALL, CV_Unsigned, lua_profile_OnChange, 0, NULL, NULL, 0, 0, NULL};
// only there to better keep track of it globally
consvar_t cv_director = {"director", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -600,6 +604,12 @@ void D_RegisterServerCommands(void)
Forceskin_cons_t[i].value = 0;
Forceskin_cons_t[i].strvalue = NULL;
}
// Set default player names
// Monster Iestyn (12/08/19): not sure where else I could have actually put this, but oh well
for (i = 0; i < MAXPLAYERS; i++)
snprintf(player_names[i], sizeof(player_names[i]), "Player %d", 1 + i);
RegisterNetXCmd(XD_NAMEANDCOLOR, Got_NameAndColor);
RegisterNetXCmd(XD_WEAPONPREF, Got_WeaponPref);
RegisterNetXCmd(XD_MAP, Got_Mapcmd);
@@ -934,6 +944,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_palette);
CV_RegisterVar(&cv_palettenum);
CV_RegisterVar(&cv_lua_profile);
// m_menu.c
CV_RegisterVar(&cv_chatheight);
CV_RegisterVar(&cv_chatwidth);
@@ -1276,7 +1288,8 @@ static boolean EnsurePlayerNameIsGood(char *name, INT32 playernum)
else if (len == 1) // Agh!
{
// Last ditch effort...
sprintf(name, "%d", M_RandomKey(10));
snprintf(name, MAXPLAYERNAME+1, "%d", M_RandomKey(10));
if (!EnsurePlayerNameIsGood(name, playernum))
return false;
}
@@ -2330,11 +2343,12 @@ static char *ConcatCommandArgv(int start, int end)
if (!p)
I_Error("ConcatCommandArgv: Out of memory!\n");
--end;/* handle the final argument separately */
--end; /* handle the final argument separately */
for (i = start; i < end; ++i)
{
p += sprintf(p, "%s ", COM_Argv(i));
if (size - (p - final) > 0)
p += snprintf(p, size - (p - final), "%s ", COM_Argv(i));
}
/* at this point "end" is actually the last argument's position */
@@ -2748,11 +2762,11 @@ static void Command_ReplayMarker(void)
if (title)
{
snprintf(demo.titlename, 64, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
snprintf(demo.titlename, sizeof(demo.titlename)-1, "%s [%i:%02d/%.5s]", title, G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
Z_Free(title);
}
else
snprintf(demo.titlename, 64, "[%i:%02d/%.5s]", G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
snprintf(demo.titlename, sizeof(demo.titlename)-1, "[%i:%02d/%.5s]", G_TicsToMinutes(adjustedleveltime, false), G_TicsToSeconds(adjustedleveltime), modeattacking ? "Record Attack" : connectedservername);
CONS_Printf("Replay will be saved!\n");
}
@@ -4349,13 +4363,13 @@ static void Got_RequestAddfilecmd(const UINT8 **cp, INT32 playernum)
char message[275];
if (toomany)
sprintf(message, M_GetText("Too many files loaded to add %s\n"), filename);
snprintf(message, sizeof(message), M_GetText("Too many files loaded to add %s\n"), filename);
else if (ncs == FS_NOTFOUND)
sprintf(message, M_GetText("The server doesn't have %s\n"), filename);
snprintf(message, sizeof(message), M_GetText("The server doesn't have %s\n"), filename);
else if (ncs == FS_MD5SUMBAD)
sprintf(message, M_GetText("Checksum mismatch on %s\n"), filename);
snprintf(message, sizeof(message), M_GetText("Checksum mismatch on %s\n"), filename);
else
sprintf(message, M_GetText("Unknown error finding wad file (%s)\n"), filename);
snprintf(message, sizeof(message), M_GetText("Unknown error finding wad file (%s)\n"), filename);
CONS_Printf("%s",message);
@@ -5189,8 +5203,10 @@ static void Command_Mapmd5_f(void)
{
INT32 i;
char md5tmp[33];
for (i = 0; i < 16; ++i)
sprintf(&md5tmp[i*2], "%02x", mapmd5[i]);
snprintf(&md5tmp[i*2], 3, "%02x", mapmd5[i]);
CONS_Printf("%s: %s\n", G_BuildMapName(gamemap), md5tmp);
}
else
+2
View File
@@ -189,6 +189,8 @@ extern consvar_t cv_ps_thinkframe_page;
extern consvar_t cv_ps_samplesize;
extern consvar_t cv_ps_descriptor;
extern consvar_t cv_lua_profile;
extern consvar_t cv_director, cv_kartdebugdirector, cv_showdirectorhud;
extern consvar_t cv_showtrackaddon;
+6 -4
View File
@@ -299,10 +299,13 @@ boolean CL_CheckDownloadable(void)
{
INT32 j;
char md5tmp[33];
for (j = 0; j < 16; j++)
sprintf(&md5tmp[j*2], "%02x", fileneeded[i].md5sum[j]);
snprintf(&md5tmp[j*2], 3, "%02x", fileneeded[i].md5sum[j]);
CONS_Printf("%s", md5tmp);
}
CONS_Printf("\n");
}
}
@@ -1616,8 +1619,7 @@ static void CURLGetFile(void)
#endif
}
HTTP_login *
CURLGetLogin (const char *url, HTTP_login ***return_prev_next)
HTTP_login *CURLGetLogin(const char *url, HTTP_login ***return_prev_next)
{
HTTP_login * login;
HTTP_login ** prev_next;
@@ -1627,7 +1629,7 @@ CURLGetLogin (const char *url, HTTP_login ***return_prev_next)
( login = (*prev_next));
prev_next = &login->next
){
if (fastcmp(login->url, url) != 0)
if (fastcmp(login->url, url))
{
if (return_prev_next)
(*return_prev_next) = prev_next;
+2 -2
View File
@@ -211,12 +211,12 @@ void D_SetupProtocol(void)
if (result)
{
if (!fastcmp(buffer, "no"))
if (fastcmp(buffer, "no"))
{
fclose(fp);
return;
}
else if (fastcmp(buffer, exe_path))
else if (!fastcmp(buffer, exe_path))
{
// overwrite
fclose(fp);
+49 -27
View File
@@ -542,7 +542,7 @@ void I_OutputMsg(const char *fmt, ...)
I_Error("I_OutputMsg: Out of memory!\n");
va_start(argptr, fmt);
vsprintf(txt, fmt, argptr);
vsnprintf(txt, len+1, fmt, argptr);
va_end(argptr);
#ifdef HAVE_TTF
@@ -550,7 +550,7 @@ void I_OutputMsg(const char *fmt, ...)
DEFAULTFONTBGR, DEFAULTFONTBGG, DEFAULTFONTBGB, DEFAULTFONTBGA, txt);
#endif
len = strlen(txt);
len = strnlen(txt, len+1);
#ifdef LOGMESSAGES
if (logstream)
@@ -968,14 +968,18 @@ void I_Sleep(UINT32 ms)
void I_SleepDuration(precise_t duration)
{
#if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__OpenBSD__)
UINT64 precision = I_GetPrecisePrecision();
struct timespec ts = {
.tv_sec = duration / precision,
.tv_nsec = duration * 1000000000 / precision % 1000000000,
};
int status;
#ifdef __OpenBSD__
do status = nanosleep(&ts, &ts);
#else
do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
#endif
while (status == EINTR);
#elif defined (MIN_SLEEP_DURATION_MS)
UINT64 precision = I_GetPrecisePrecision();
@@ -1053,7 +1057,7 @@ static void I_PrintSignal(INT32 signal_num, boolean core_dumped, char *signal_ms
sigmsg = ("SIGABRT - SRB2Kart-Saturn was terminated by an abort signal.");
break;
default:
sprintf(signal_msg, "Signal number %d", signal_num);
snprintf(signal_msg, 512, "Signal number %d", signal_num);
sigmsg = (core_dumped ? "Unknown signal" : signal_msg);
break;
}
@@ -1061,13 +1065,17 @@ static void I_PrintSignal(INT32 signal_num, boolean core_dumped, char *signal_ms
if (core_dumped)
{
if (sigmsg)
sprintf(signal_msg, "%s (core dumped)", sigmsg);
{
snprintf(signal_msg, 512, "%s (core dumped)", sigmsg);
}
else
{
strcat(signal_msg, " (core dumped)");
}
}
else
{
sprintf(signal_msg, "%s", sigmsg);
snprintf(signal_msg, 512, "%s", sigmsg);
}
}
@@ -1344,7 +1352,7 @@ FUNCNORETURN static ATTRNORETURN void newsignalhandler_Warn(const char *pr)
{
char text[128];
snprintf(text, sizeof text,
snprintf(text, sizeof(text),
"Error while setting up signal reporting: %s: %s",
pr,
strerror(errno)
@@ -1530,7 +1538,7 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...)
if (errorcount > 20)
{
va_start(argptr, error);
vsnprintf(buffer, 8192, error, argptr);
vsnprintf(buffer, sizeof(buffer), error, argptr);
va_end(argptr);
I_OutputMsg("SRB2Kart %s Recursive Error", buffer);
@@ -1543,7 +1551,7 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...)
// Display error message in the console before we start shutting it down
va_start(argptr, error);
vsnprintf(buffer, 8192, error, argptr);
vsnprintf(buffer, sizeof(buffer), error, argptr);
va_end(argptr);
I_OutputMsg("\nI_Error(): %s\n", buffer);
@@ -1764,7 +1772,8 @@ char *I_GetUserName(void)
}
}
}
strncpy(username, p, MAXPLAYERNAME);
snprintf(username, sizeof(username), "%s", p);
}
if (!fastcmp(username, ""))
@@ -1788,6 +1797,24 @@ INT32 I_mkdir(const char *dirname, INT32 unixright)
#endif
}
INT32 I_ChDir(const char *path)
{
#ifdef _WIN32
return (SetCurrentDirectoryA(path) ? 0 : -1);
#else
return chdir(path);
#endif
}
char *I_GetCwd(char *buf, size_t size)
{
#ifdef _WIN32
return (GetCurrentDirectoryA((DWORD)size, buf) ? buf : NULL);
#else
return getcwd(buf, size);
#endif
}
char *I_GetEnv(const char *name)
{
return getenv(name);
@@ -1820,28 +1847,23 @@ const char *I_ClipboardPaste(void)
*/
static boolean isWadPathOk(const char *path)
{
char *wad3path = (char*)(malloc(256));
char wad3path[256];
if (!wad3path)
return false;
sprintf(wad3path, pandf, path, WADKEYWORD);
snprintf(wad3path, sizeof(wad3path), pandf, path, WADKEYWORD);
if (FIL_ReadFileOK(wad3path))
{
free(wad3path);
return true;
}
free(wad3path);
return false;
}
static void pathonly(char *s)
static void pathonly(char *s, size_t size)
{
size_t j;
for (j = strlen(s); j != (size_t)-1; j--)
for (j = strnlen(s, size); j != (size_t)-1; j--)
{
if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/'))
{
@@ -1868,11 +1890,12 @@ static const char *searchWad(const char *searchDir)
static char tempsw[256] = "";
filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD);
snprintf(tempsw, sizeof(tempsw), "%s", WADKEYWORD);
fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);
pathonly(tempsw, sizeof(tempsw));
return tempsw;
}
@@ -1910,7 +1933,7 @@ static const char *locateWad(void)
#ifndef NOCWD
// examine current dir
strcpy(returnWadPath, ".");
snprintf(returnWadPath, sizeof(returnWadPath), "%s", ".");
I_OutputMsg(",%s", returnWadPath);
if (isWadPathOk(returnWadPath))
return NULL;
@@ -1922,7 +1945,7 @@ static const char *locateWad(void)
// examine user jart directory
if ((envstr = I_GetEnv("HOME")) != NULL)
{
sprintf(returnWadPath, "%s" PATHSEP DEFAULTDIR, envstr);
snprintf(returnWadPath, sizeof(returnWadPath), "%s" PATHSEP DEFAULTDIR, envstr);
CHECKWADPATH(returnWadPath);
}
#endif
@@ -1936,7 +1959,7 @@ static const char *locateWad(void)
// examine default dirs
for (i = 0; wadDefaultPaths[i]; i++)
{
strcpy(returnWadPath, wadDefaultPaths[i]);
snprintf(returnWadPath, sizeof(returnWadPath), "%s", wadDefaultPaths[i]);
CHECKWADPATH(returnWadPath);
}
@@ -1964,12 +1987,11 @@ const char *I_LocateWad(void)
// change to the directory where we found srb2.srb
#if defined (_WIN32)
waddir = _fullpath(NULL, waddir, MAX_PATH);
SetCurrentDirectoryA(waddir);
#else
waddir = realpath(waddir, NULL);
if (waddir == NULL || chdir(waddir) == -1)
I_OutputMsg("Couldn't change working directory\n");
#endif
if (waddir == NULL || I_ChDir(waddir) == -1)
I_OutputMsg("Couldn't change working directory\n");
}
return waddir;
+1 -1
View File
@@ -402,7 +402,7 @@ static void Discordrp_OnChange(void)
static void DRPC_GotServerIP(UINT32 address)
{
const unsigned char * p = (const unsigned char *)&address;
sprintf(self_ip, "%u.%u.%u.%u:%u", p[0], p[1], p[2], p[3], current_port);
snprintf(self_ip, IP_SIZE+1, "%u.%u.%u.%u:%u", p[0], p[1], p[2], p[3], current_port);
}
/*--------------------------------------------------
+4 -4
View File
@@ -130,8 +130,8 @@ extern char logfilename[1024];
#else
#define VERSION 1 // Game version
#define SUBVERSION 6 // more precise version number
#define VERSIONSTRING "Saturn v9.3"
#define VERSIONSTRINGW L"Saturn v9.3"
#define VERSIONSTRING "Saturn v10"
#define VERSIONSTRINGW L"Saturn v10"
#define SATURN_TESTING // comment out for saturn release builds!
@@ -604,8 +604,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
// undefine to enable fixes and features that are not vanilla compatible
#define COMPAT_VANILLA
// if we build with 32 player (or more!) support we dont need to care vanilla compat
#if MAXPLAYERS > 16
// if we build with 32 player (or more or less!) support we dont need to care about vanilla compat
#if MAXPLAYERS != 16
#undef COMPAT_VANILLA
#endif
+2 -1
View File
@@ -111,7 +111,8 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum)
goto freemask;
// SRB2Kart: This suddenly triggers ERRORMODE now
//sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)masknum, (UINT16)scrnnum);
//snprintf(&lumpname[4], 3, "%.2hu%.2hu", (UINT16)masknum, (UINT16)scrnnum);
//lumpname[8] = 0;
lumpname[4] = '0'+(masknum/10);
lumpname[5] = '0'+(masknum%10);
+30 -30
View File
@@ -1723,11 +1723,11 @@ void G_BeginRecording(void)
// Print to a separate temp buffer instead of demo.titlename, so we can use it in M_TextInputSetString
if (title)
{
snprintf(demotitlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
snprintf(demotitlename, sizeof(demotitlename)-1, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername);
Z_Free(title);
}
else
snprintf(demotitlename, 64, "%s", modeattacking ? "Time Attack" : connectedservername);
snprintf(demotitlename, sizeof(demotitlename)-1, "%s", modeattacking ? "Time Attack" : connectedservername);
// Init just in case it isn't initialized already
M_TextInputInit(&demo.titlenameinput, demo.titlename, sizeof(demo.titlename));
@@ -2212,7 +2212,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
{
CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath);
pdemo->type = MD_INVALID;
sprintf(pdemo->title, "INVALID REPLAY");
snprintf(pdemo->title, sizeof(pdemo->title), "INVALID REPLAY");
return;
}
@@ -2222,7 +2222,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
{
CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath);
pdemo->type = MD_INVALID;
sprintf(pdemo->title, "INVALID REPLAY");
snprintf(pdemo->title, sizeof(pdemo->title), "INVALID REPLAY");
return;
}
@@ -2247,14 +2247,14 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
#ifdef DEMO_COMPAT_100
case 0x0001:
pdemo->type = MD_OUTDATED;
sprintf(pdemo->title, "Legacy Replay");
snprintf(pdemo->title, sizeof(pdemo->title), "Legacy Replay");
break;
#endif
// too old, cannot support.
default:
CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath);
pdemo->type = MD_INVALID;
sprintf(pdemo->title, "INVALID REPLAY");
snprintf(pdemo->title, sizeof(pdemo->title), "INVALID REPLAY");
return;
}
@@ -2267,7 +2267,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
{
CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath);
pdemo->type = MD_INVALID;
sprintf(pdemo->title, "INVALID REPLAY");
snprintf(pdemo->title, sizeof(pdemo->title), "INVALID REPLAY");
return;
}
@@ -2288,7 +2288,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
{
CONS_Alert(CONS_ERROR, M_GetText("%s is a legacy multiplayer replay and cannot be played.\n"), pdemo->filepath);
pdemo->type = MD_INVALID;
sprintf(pdemo->title, "INVALID REPLAY");
snprintf(pdemo->title, sizeof(pdemo->title), "INVALID REPLAY");
return;
}
#endif
@@ -2522,7 +2522,7 @@ void G_LoadDemoTitle(menudemo_t *pdemo)
if (!handle)
{
CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath);
sprintf(pdemo->title, "INVALID REPLAY");
snprintf(pdemo->title, sizeof(pdemo->title), "INVALID REPLAY");
return;
}
@@ -2534,7 +2534,7 @@ void G_LoadDemoTitle(menudemo_t *pdemo)
if (count < 96 || memcmp(info_p, DEMOHEADER, 12))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath);
sprintf(pdemo->title, "INVALID REPLAY");
snprintf(pdemo->title, sizeof(pdemo->title), "INVALID REPLAY");
return;
}
@@ -2563,13 +2563,13 @@ void G_LoadDemoTitle(menudemo_t *pdemo)
break;
#ifdef DEMO_COMPAT_100
case 0x0001:
sprintf(pdemo->title, "Legacy Replay");
snprintf(pdemo->title, sizeof(pdemo->title), "Legacy Replay");
break;
#endif
// too old, cannot support.
default:
CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath);
sprintf(pdemo->title, "INVALID REPLAY");
snprintf(pdemo->title, sizeof(pdemo->title), "INVALID REPLAY");
}
}
@@ -2633,7 +2633,7 @@ void G_DoPlayDemo(char *defdemoname)
//FIL_DefaultExtension(defdemoname, ".lmp");
if (!FIL_ReadFile(defdemoname, &demobuf.buffer))
{
snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname);
snprintf(msg, sizeof(msg), M_GetText("Failed to read file '%s'.\n"), defdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
gameaction = ga_nothing;
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
@@ -2645,7 +2645,7 @@ void G_DoPlayDemo(char *defdemoname)
// load demo resource from WAD
else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
{
snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
snprintf(msg, sizeof(msg), M_GetText("Failed to read lump '%s'.\n"), defdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
gameaction = ga_nothing;
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
@@ -2666,7 +2666,7 @@ void G_DoPlayDemo(char *defdemoname)
if (memcmp(demobuf.p, DEMOHEADER, 12))
{
snprintf(msg, 1024, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s is not a SRB2Kart replay file.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2692,7 +2692,7 @@ void G_DoPlayDemo(char *defdemoname)
#endif
// too old, cannot support.
default:
snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2703,7 +2703,7 @@ void G_DoPlayDemo(char *defdemoname)
if (memcmp(demobuf.p, "PLAY", 4))
{
snprintf(msg, 1024, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2720,7 +2720,7 @@ void G_DoPlayDemo(char *defdemoname)
{
if (demoflags & DF_MULTIPLAYER)
{
snprintf(msg, 1024, M_GetText("%s is an alpha multiplayer replay and cannot be played.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s is an alpha multiplayer replay and cannot be played.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2747,31 +2747,31 @@ void G_DoPlayDemo(char *defdemoname)
switch (error)
{
case DFILE_ERROR_NOTLOADED:
snprintf(msg, 1024,
snprintf(msg, sizeof(msg),
"Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n",
pdemoname);
break;
case DFILE_ERROR_OUTOFORDER:
snprintf(msg, 1024,
snprintf(msg, sizeof(msg),
"Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n",
pdemoname);
break;
case DFILE_ERROR_INCOMPLETEOUTOFORDER:
snprintf(msg, 1024,
snprintf(msg, sizeof(msg),
"Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n",
pdemoname);
break;
case DFILE_ERROR_CANNOTLOAD:
snprintf(msg, 1024,
snprintf(msg, sizeof(msg),
"Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n",
pdemoname);
break;
case DFILE_ERROR_EXTRAFILES:
snprintf(msg, 1024,
snprintf(msg, sizeof(msg),
"You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n",
pdemoname);
break;
@@ -2821,7 +2821,7 @@ void G_DoPlayDemo(char *defdemoname)
// ...*map* not loaded?
if (!gamemap || (gamemap > NUMMAPS) || (W_CheckNumForName(G_BuildMapName(gamemap)) == LUMPERROR))
{
snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s features a course that is not currently loaded.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2853,7 +2853,7 @@ void G_DoPlayDemo(char *defdemoname)
// Skin not loaded?
if (!SetPlayerSkin(0, skin))
{
snprintf(msg, 1024, M_GetText("%s features a character that is not currently loaded.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s features a character that is not currently loaded.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2863,7 +2863,7 @@ void G_DoPlayDemo(char *defdemoname)
// ...*map* not loaded?
if (!gamemap || (gamemap > NUMMAPS) || !mapheaderinfo[gamemap-1] || !(mapheaderinfo[gamemap-1]->menuflags & LF2_EXISTSHACK))
{
snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s features a course that is not currently loaded.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2886,7 +2886,7 @@ void G_DoPlayDemo(char *defdemoname)
// Sigh ... it's an empty demo.
if (*demobuf.p == DEMOMARKER)
{
snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s contains no data to be played.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2924,7 +2924,7 @@ void G_DoPlayDemo(char *defdemoname)
// Sigh ... it's an empty demo.
if (*demobuf.p == DEMOMARKER)
{
snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s contains no data to be played.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2973,7 +2973,7 @@ void G_DoPlayDemo(char *defdemoname)
if (modeattacking)
{
snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with spectators, and is thus invalid.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s is a Record Attack replay with spectators, and is thus invalid.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
@@ -2985,7 +2985,7 @@ void G_DoPlayDemo(char *defdemoname)
if (modeattacking && numslots > 1)
{
snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with multiple players, and is thus invalid.\n"), pdemoname);
snprintf(msg, sizeof(msg), M_GetText("%s is a Record Attack replay with multiple players, and is thus invalid.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, M_ReturnToTitleFromError, MM_EVENTHANDLER);
G_ResetDemoPlayback();
+23 -34
View File
@@ -453,34 +453,13 @@ consvar_t cv_driftsparkpulse = {"driftsparkpulse", "1.4", CV_FLOAT | CV_SAVE, dr
static CV_PossibleValue_t cechotoggle_t[] = {{0, "Off"}, {1, "On"}, {2, "Console"}, {0, NULL}};
consvar_t cv_cechotoggle = {"show_cecho", "On", CV_SAVE, cechotoggle_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#if MAXPLAYERS > 16
#error "please update player_name table using the new value for MAXPLAYERS"
#endif
#ifdef SEENAMES
player_t *seenplayer = NULL; // player we're aiming at right now
#endif
char player_names[MAXPLAYERS][MAXPLAYERNAME+1] =
{
"Player 1",
"Player 2",
"Player 3",
"Player 4",
"Player 5",
"Player 6",
"Player 7",
"Player 8",
"Player 9",
"Player 10",
"Player 11",
"Player 12",
"Player 13",
"Player 14",
"Player 15",
"Player 16"
}; // SRB2kart - removed Players 17 through 32
// now automatically allocated in D_RegisterServerCommands
// so that it doesn't have to be updated depending on the value of MAXPLAYERS
char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
INT32 player_name_changes[MAXPLAYERS] = {};
INT16 rw_maximums[NUM_WEAPONS] =
@@ -625,14 +604,18 @@ const char *G_BuildMapName(INT32 map)
}
if (map < 100 && map >= 0) // ...but why use signed integer in first place? idk but this prevents warning (and potential buffer overflow lol)
sprintf(&mapname[3], "%.2d", map);
{
snprintf(&mapname[3], sizeof(mapname)-3, "%.2d", map);
}
else
{
mapname[3] = (char)('A' + (char)((map - 100) / 36));
if ((map - 100) % 36 < 10)
mapname[4] = (char)('0' + (char)((map - 100) % 36));
else
mapname[4] = (char)('A' + (char)((map - 100) % 36) - 10);
mapname[5] = '\0';
}
@@ -2647,12 +2630,18 @@ mapthing_t *G_FindRaceStart(INT32 playernum)
// Just spawn there.
//return playerstarts[0];
#if MAXPLAYERS > 16
//this section courtesy of fickle - v1.1 battle royale
// screw collision chex
return playerstarts[pos % numcoopstarts];
#else
if (P_IsLocalPlayerNum(playernum))
{
CONS_Alert(CONS_WARNING, "Could not spawn at any Race starts!\n");
}
return NULL;
#endif
}
if (P_IsLocalPlayerNum(playernum))
@@ -3787,7 +3776,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
startonmapnum = mapoverride;
#endif
sprintf(savename, savegamename, slot);
snprintf(savename, sizeof(savename), savegamename, slot);
length = FIL_ReadFile(savename, &save.buffer);
if (!length)
@@ -3799,7 +3788,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
save.p = save.buffer;
memset(vcheck, 0, sizeof (vcheck));
sprintf(vcheck, "version %d", VERSION);
snprintf(vcheck, sizeof(vcheck), "version %d", VERSION);
if (!fastcmp((const char *)save.p, (const char *)vcheck))
{
@@ -3865,8 +3854,8 @@ void G_SaveGame(UINT32 savegameslot)
const char *backup;
savebuffer_t save = {};
sprintf(savename, savegamename, savegameslot);
backup = va("%s",savename);
snprintf(savename, sizeof(savename), savegamename, savegameslot);
backup = va("%s", savename);
// save during evaluation or credits? game's over, folks!
if (gamestate == GS_CREDITS || gamestate == GS_EVALUATION)
@@ -3884,8 +3873,8 @@ void G_SaveGame(UINT32 savegameslot)
return;
}
memset(name, 0, sizeof (name));
sprintf(name, "version %d", VERSION);
memset(name, 0, sizeof(name));
snprintf(name, sizeof(name), "version %d", VERSION);
WRITEMEM(save.p, name, VERSIONSIZE);
P_SaveGame(&save);
@@ -4114,12 +4103,12 @@ char *G_BuildMapTitle(INT32 mapnum)
if (!title)
return NULL;
sprintf(title, "%s", mapheaderinfo[mapnum-1]->lvlttl);
snprintf(title, len, "%s", mapheaderinfo[mapnum-1]->lvlttl);
if (zonetext)
sprintf(title + strlen(title), " %s", zonetext);
snprintf(title + strlen(title), len - strlen(title), " %s", zonetext);
if (actnum)
sprintf(title + strlen(title), " %s", actnum);
snprintf(title + strlen(title), len - strlen(title), " %s", actnum);
}
return title;
+2 -1
View File
@@ -1250,7 +1250,8 @@ const char *G_KeynumToString(INT32 keynum)
return keynames[j].name;
// create a name for unknown keys
sprintf(keynamestr, "KEY%d", keynum);
snprintf(keynamestr, sizeof(keynamestr), "KEY%d", keynum);
return keynamestr;
}
+6 -5
View File
@@ -346,15 +346,15 @@ static void SplitPoly (fdivline_t *dlnp, // splitting parametric line
}
// checks if any line is a portal or horizonline, for optimization
static inline void CheckForPortalsAndHorizonLines(seg_t *lseg, const line_t *line)
static inline void CheckForPortalsAndHorizonLines(boolean firstside, const line_t *line)
{
// portal check
if (!gl_maphasportals && lseg->side == 0 && line->special == PORTALSPECIAL)
if (!gl_maphasportals && firstside && line->special == PORTALSPECIAL)
{
// Find the other side!
INT32 line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->tag, -1);
if (line == &lines[line2])
if (line2 >= 0 && line == &lines[line2])
line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->tag, line2);
if (line2 >= 0) // found it!
@@ -397,7 +397,7 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 segcount, poly_t *poly)
if (!line)
continue;
CheckForPortalsAndHorizonLines(lseg, line);
CheckForPortalsAndHorizonLines(lseg->side == 0, line);
if (line->sidenum[1] != NO_INDEX)
{
@@ -581,7 +581,8 @@ static void loading_status(void)
I_OsPolling();
CON_Drawer();
sprintf(s, "%d%%", (++ls_percent)<<1);
snprintf(s, sizeof(s), "%d%%", (++ls_percent)<<1);
x = BASEVIDWIDTH/2;
y = BASEVIDHEIGHT/2;
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); // Black background to match fade in effect
+3 -2
View File
@@ -555,7 +555,8 @@ static void HWR_FreePatchCache(boolean freeall)
callback = FreeColormapsCallback;
//Z_IterateTags(PU_PATCH, PU_PATCH_ROTATED, callback);
Z_IterateTags(PU_PATCH, PU_PATCH, callback);
//Z_IterateTags(PU_PATCH, PU_PATCH_LOWPRIORITY, callback); // we dont really need to free low priority patches here as P_FreeLevelState takes care of them
Z_IterateTag(PU_PATCH, callback);
Z_IterateTags(PU_SPRITE, PU_HUDGFX, callback);
}
@@ -998,7 +999,7 @@ static void HWR_CacheFlat(GLMipmap_t *glMipmap, lumpnum_t flatlumpnum)
const char *flatname = W_CheckNameForNum(flatlumpnum);
// hack for gba rainbow roads cyan floors
if (UNLIKELY(memcmp(flatname, "GBA_RRF5", 8) == 0 && flatname[8] == 0))
if (UNLIKELY(flatname && memcmp(flatname, "GBA_RRF5", 8) == 0 && flatname[8] == 0))
{
glMipmap->flags &= ~TF_CHROMAKEYED;
}
+1
View File
@@ -191,6 +191,7 @@ enum
SHADER_SPRITE,
SHADER_MODEL,
SHADER_WATER,
SHADER_WATERREFRACT,
SHADER_FOG,
SHADER_SKY,
SHADER_PALETTE_POSTPROCESS,
+1
View File
@@ -39,6 +39,7 @@ void GL_EnableStencilTest(void);
void GL_DisableStencilTest(void);
void GL_DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
void GL_DrawWaterPolygon(FOutVector *pOutVerts, FUINT iNumPts);
void GL_DrawIndexedTriangles(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray);
void GL_Draw2DLine(F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
+281 -18
View File
@@ -103,6 +103,8 @@ static constexpr INT32 bsp_culling_distances[] = {
// Performance stats
ps_metric_t ps_hw_nodesorttime = {};
ps_metric_t ps_hw_nodedrawtime = {};
ps_metric_t ps_hw_waterdrawtime = {};
ps_metric_t ps_hw_spritesorttime = {};
ps_metric_t ps_hw_spritedrawtime = {};
@@ -514,7 +516,7 @@ static FUINT HWR_CalcWallLight(FUINT lightnum, seg_t *seg, extracolormap_t *colo
const INT16 offset = (cv_glfakecontrast.value == 2) ? seg->hwLightOffset : ((INT16)seg->lightOffset * 8);
finallight += offset;
finallight = CLAMP(finallight, 0 , 255);
finallight = CLAMP(finallight, 0, 255);
}
return (FUINT)finallight;
@@ -532,7 +534,7 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope, const sector_t
const INT16 offset = (cv_glfakecontrast.value == 2) ? slope->hwLightOffset : ((INT16)slope->lightOffset * 8);
finallight += (fof ? -offset : offset);
finallight = CLAMP(finallight, 0 , 255);
finallight = CLAMP(finallight, 0, 255);
}
return (FUINT)finallight;
@@ -712,7 +714,9 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
if (PolyFlags & PF_Fog)
shader = SHADER_FOG;
else if (cv_ripplewater.value && (PolyFlags & PF_Ripple))
{
shader = SHADER_WATER;
}
else
shader = SHADER_FLOOR;
@@ -807,6 +811,164 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
#undef SETUP3DVERT
}
// cut down version of HWR_RenderPlane
// which renders only the refracted scene in place of planes
// FIXME: we probably could just use stencil stuff for this
// but i hate messing with that
static void HWR_RenderRefractionPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, sector_t *FOFsector)
{
FOutVector *v3d;
polyvertex_t *pv;
pslope_t *slope = NULL;
size_t nrPlaneVerts;
INT32 i;
float height; // constant y for all points on the convex flat polygon
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
poly_t *planepoly = xsub->planepoly;
// no convex poly were generated for this subsector
if (!planepoly)
return;
nrPlaneVerts = planepoly->numpts;
if (nrPlaneVerts < 3) // not even a triangle ?
return;
const sector_t *sec = FOFsector;
// Get the slope pointer to simplify future code
if (!isceiling && sec->f_slope)
slope = sec->f_slope;
else if (isceiling && sec->c_slope)
slope = sec->c_slope;
height = FixedToFloat(fixedheight);
// Allocate plane-vertex buffer if we need to
if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts)
{
numAllocedPlaneVerts = (UINT16)nrPlaneVerts;
Z_Free(planeVerts);
Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
}
pv = planepoly->pts;
#define SETUP3DVERT(vert, vx, vy) {\
vert->s = 0.0f;\
vert->t = 0.0f;\
\
if (slope)\
{\
fixedheight = P_GetSlopeZAt(slope, FloatToFixed((vx)), FloatToFixed((vy)));\
height = FixedToFloat(fixedheight);\
}\
\
vert->x = (vx);\
vert->y = height;\
vert->z = (vy);\
\
}
for (i = 0, v3d = planeVerts; i < (INT32)nrPlaneVerts; i++, v3d++, pv++)
SETUP3DVERT(v3d, pv->x, pv->y);
GL_DrawWaterPolygon(planeVerts, nrPlaneVerts);
//FIXME: horizonlines with fofs dont work in gl for some reason!
(void)subsector;
/*if (gl_maphashorizonlines && subsector && cv_glhorizonlines.value)
{
// Horizon lines
FOutVector horizonpts[6];
float dist, vx, vy;
float x1, y1, xd, yd;
UINT8 numplanes, j;
vertex_t v; // For determining the closest distance from the line to the camera, to split render planes for minimum distortion;
static constexpr float renderdist = 27000.0f; // How far out to properly render the plane
static constexpr float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion
const seg_t *line = &segs[subsector->firstline];
for (i = 0; i < subsector->numlines; i++, line++)
{
if (line->polyseg)
continue;
line_t* ld = line->linedef;
// this check sucks and is a hotspot lel
if (LIKELY(ld->special != HORIZONSPECIAL))
continue;
if (R_PointOnSegSide(viewx, viewy, line) != 0)
continue;
P_ClosestPointOnLine(viewx, viewy, ld, &v);
dist = FixedToFloat(R_PointToDist(v.x, v.y));
x1 = (line->fv1.x);
y1 = (line->fv1.y);
xd = (line->fv2.x) - x1;
yd = (line->fv2.y) - y1;
// Based on the seg length and the distance from the line, split horizon into multiple poly sets to reduce distortion
dist = sqrtf((xd*xd) + (yd*yd)) / dist / 16.0f;
if (dist > 100.0f)
numplanes = 100;
else
numplanes = (UINT8)dist + 1;
for (j = 0; j < numplanes; j++)
{
// Left side
vx = x1 + xd * j / numplanes;
vy = y1 + yd * j / numplanes;
SETUP3DVERT((&horizonpts[1]), vx, vy);
dist = sqrtf(powf(vx - gl_viewx, 2) + powf(vy - gl_viewy, 2));
vx = (vx - gl_viewx) * renderdist / dist + gl_viewx;
vy = (vy - gl_viewy) * renderdist / dist + gl_viewy;
SETUP3DVERT((&horizonpts[0]), vx, vy);
// Right side
vx = x1 + xd * (j+1) / numplanes;
vy = y1 + yd * (j+1) / numplanes;
SETUP3DVERT((&horizonpts[2]), vx, vy);
dist = sqrtf(powf(vx - gl_viewx, 2) + powf(vy - gl_viewy, 2));
vx = (vx - gl_viewx) * renderdist / dist + gl_viewx;
vy = (vy - gl_viewy) * renderdist / dist + gl_viewy;
SETUP3DVERT((&horizonpts[3]), vx, vy);
// Horizon fills
vx = (horizonpts[0].x - gl_viewx) * farrenderdist / renderdist + gl_viewx;
vy = (horizonpts[0].z - gl_viewy) * farrenderdist / renderdist + gl_viewy;
SETUP3DVERT((&horizonpts[5]), vx, vy);
horizonpts[5].y = gl_viewz;
vx = (horizonpts[3].x - gl_viewx) * farrenderdist / renderdist + gl_viewx;
vy = (horizonpts[3].z - gl_viewy) * farrenderdist / renderdist + gl_viewy;
SETUP3DVERT((&horizonpts[4]), vx, vy);
horizonpts[4].y = gl_viewz;
// Draw
GL_DrawWaterPolygon(&Surf, horizonpts, 6, PF_NoTexture|PF_Ripple);
}
}
}
*/
#undef SETUP3DVERT
}
#ifdef WALLSPLATS
static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
{
@@ -1101,8 +1263,8 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
// Found a break
// The heights are clamped to ensure the polygon doesn't cross itself.
bot = std::clamp(bheight, realbot, top);
endbot = std::clamp(endbheight, endrealbot, endtop);
bot = std::min(std::max(bheight, realbot), top);
endbot = std::min(std::max(endbheight, endrealbot), endtop);
Surf->PolyColor.s.alpha = alpha;
@@ -2306,7 +2468,7 @@ static inline void DoAddLine(seg_t* line, angle_t angle1, angle_t angle2)
// Find the other side!
INT32 line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->linedef->tag, -1);
if (line->linedef == &lines[line2])
if (line2 >= 0 && line->linedef == &lines[line2])
line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->linedef->tag, line2);
if (line2 >= 0) // found it!
@@ -3235,6 +3397,18 @@ static void HWR_DrawSpriteShadow(gl_vissprite_t *spr, patch_t *gpatch, GLPatch_t
if (!spr->mobj)
return;
// Ceiling scenery have no shadow.
if ((spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) == (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY))
return;
// Debris have no corona or shadow.
if (spr->mobj->flags2 & MF2_DEBRIS)
return;
// Without this, your shadow shows on the floor, even after you die and fall through the ground.
if (spr->mobj->z < spr->mobj->floorz)
return;
R_GetShadowZ(spr->mobj, &floorslope);
mobjfloor = HWR_OpaqueFloorAtPos(
@@ -3495,10 +3669,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr, const boolean papersprite)
hwrpatch = static_cast<GLPatch_t *>(gpatch->hardware);
// Draw shadow BEFORE sprite
if (UNLIKELY(cv_shadow.value // Shadows enabled
&& (sprmo->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
&& !(sprmo->flags2 & MF2_DEBRIS) // Debris have no corona or shadow.
&& (sprmo->z >= sprmo->floorz))) // Without this, your shadow shows on the floor, even after you die and fall through the ground.
if (UNLIKELY(cv_shadow.value))
{
////////////////////
// SHADOW SPRITE! //
@@ -3824,10 +3995,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
}
// Draw shadow BEFORE sprite
if (UNLIKELY(cv_shadow.value // Shadows enabled
&& (sprmo->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
&& !(sprmo->flags2 & MF2_DEBRIS) // Debris have no corona or shadow.
&& (sprmo->z >= sprmo->floorz))) // Without this, your shadow shows on the floor, even after you die and fall through the ground.
if (UNLIKELY(cv_shadow.value))
{
////////////////////
// SHADOW SPRITE! //
@@ -4219,7 +4387,9 @@ static void HWR_RenderDrawNodes(void)
// Reversed order
for (i = 0; i < numdrawnodes; i++)
{
sortindex[i] = numdrawnodes - i - 1;
}
// The order is correct apart from planes in the same subsector.
// So scan the list and sort out these cases.
@@ -4295,7 +4465,6 @@ static void HWR_RenderDrawNodes(void)
HWR_RenderPolyObjectPlane(polyplane->polysector, polyplane->isceiling, polyplane->fixedheight, polyplane->blend, polyplane->lightlevel,
polyplane->lumpnum, polyplane->FOFSector, polyplane->alpha, polyplane->planecolormap);
}
break;
case DRAWNODE_WALL:
@@ -4319,6 +4488,89 @@ static void HWR_RenderDrawNodes(void)
drawnodes.clear(); // clear so our size is 0 again!
}
static void HWR_RenderRefractionWater(void)
{
// this basically just draws a refracted screen copy in the place of water planes
// best approach i can think of to handle translucent things being drawn behind water planes
// this means other translucent shit will appear "correctly" and does not cause any sorting issues
// caveat: anything translucent behind water planes will be unaffected by the refraction effect
// there just is no better way to do this unless we wanna trash performance to hell by doing a screen copy per water plane
// it "might" be possible to only partially copy the screen like the software renderer
// but that will be rather tricky to implement since we dont really have "screen bounds" we can use for this
// plus i also immensely suck at maths
static std::vector<gl_drawnode_t> waterdrawnodes;
const size_t numdrawnodes = drawnodes.size();
// no drawnodes...
if (!numdrawnodes)
return;
waterdrawnodes.reserve(DRAWNODES_INIT_SIZE/2); // surely there will be less water than other stuff, right?
// go through our drawnodes to pull out the water
// HWR_RenderDrawNodes will skip those
// we do this before since trying to capture
// anything translucent in the refraction is utter arse pain
for (size_t w = 0; w < numdrawnodes; w++)
{
gl_drawnode_t *drawnode = &drawnodes[w];
// gotta be a plane duh
if (drawnode->type != DRAWNODE_PLANE)
continue;
planeinfo_t *plane = &drawnode->u.plane;
// uh dont think we actually need this lol
// but better be safe for now
if (plane->alpha >= 255)
continue;
// this only applies to translucent water with ripple effect!
if (!(plane->blend & PF_Ripple))
continue;
waterdrawnodes.push_back(drawnodes[w]);
}
const size_t numwaterdrawnodes = waterdrawnodes.size();
// no water....
if (!numwaterdrawnodes)
return;
// this is probably a bit wasteful
// since we only copy the screen once
// but you might be able to see both planes not overlap if you look from a wonky angle
auto wotercompare = [](const void *p1, const void *p2)
{
const gl_drawnode_t *n1 = (const gl_drawnode_t *)p1;
const gl_drawnode_t *n2 = (const gl_drawnode_t *)p2;
return abs(n2->u.plane.fixedheight - viewz) -
abs(n1->u.plane.fixedheight - viewz);
};
qs22j(waterdrawnodes.data(), waterdrawnodes.size(), sizeof(gl_drawnode_t), wotercompare);
GL_SetTransform(&atransform);
GL_CopyMainFramebufferTexture();
GL_CopyMainFramebufferDepth();
// now finally render the refraction planes
for (auto &drawnode : waterdrawnodes)
{
planeinfo_t *plane = &drawnode.u.plane;
gl_frontsector = NULL;
HWR_RenderRefractionPlane(NULL, plane->xsub, plane->isceiling, plane->fixedheight, plane->FOFSector);
}
waterdrawnodes.clear();
}
// --------------------------------------------------------------------------
// Draw all vissprites
// --------------------------------------------------------------------------
@@ -5595,9 +5847,20 @@ static void HWR_RenderViewpoint(gl_portal_t *rootportal, int stencil_level, bool
HWR_DrawSprites<DrawSpritesType::kSprites>();
PS_STOP_TIMING(ps_hw_spritedrawtime);
ps_numdrawnodes.value.i = 0;
ps_hw_nodesorttime.value.p = 0;
ps_hw_nodedrawtime.value.p = 0;
ps_numdrawnodes.value.i = 0;
ps_hw_nodesorttime.value.p = 0;
ps_hw_nodedrawtime.value.p = 0;
ps_hw_waterdrawtime.value.p = 0;
// thisll be a good mess making this toggable
if (cv_ripplewater.value && HWR_UseShader() && !wireframe) // dont need this without shaders do we
{
// should we not do this during portal render?
// wonder how bad the perf will be....
PS_START_TIMING(ps_hw_waterdrawtime);
HWR_RenderRefractionWater();
PS_STOP_TIMING(ps_hw_waterdrawtime);
}
HWR_RenderDrawNodes();
@@ -6115,7 +6378,7 @@ static boolean HWR_WipeCheck(UINT8 wipenum, UINT8 scrnnum)
}
// puts the numbers into the lumpname
sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)wipenum, (UINT16)scrnnum);
snprintf(&lumpname[4], sizeof(lumpname) - 4, "%.2hu%.2hu", (UINT16)wipenum, (UINT16)scrnnum);
wipelumpnum = W_CheckNumForName(lumpname);
// again, shouldn't be here really
+1
View File
@@ -68,6 +68,7 @@ enum
// Performance stats
extern ps_metric_t ps_hw_nodesorttime;
extern ps_metric_t ps_hw_nodedrawtime;
extern ps_metric_t ps_hw_waterdrawtime;
extern ps_metric_t ps_hw_spritesorttime;
extern ps_metric_t ps_hw_spritedrawtime;
+2 -2
View File
@@ -1247,7 +1247,7 @@ void HWR_DrawMD2(gl_vissprite_t *spr)
if (!md2->model)
{
CONS_Debug(DBG_RENDER, "Loading model... (%s, %s)", sprnames[spr->mobj->sprite], md2->filename);
sprintf(filename, "mdls/%s", md2->filename);
snprintf(filename, sizeof(filename), "mdls/%s", md2->filename);
md2->model = md2_readModel(filename);
if (md2->model)
@@ -1483,7 +1483,7 @@ void HWR_Draw2DModel(md2_t *md2, INT32 x, INT32 y, INT32 skinnum, skincolors_t c
{
char filename[64];
CONS_Debug(DBG_RENDER, "Loading model... (%s)\n", md2->filename);
sprintf(filename, "mdls/%s", md2->filename);
snprintf(filename, sizeof(filename), "mdls/%s", md2->filename);
md2->model = md2_readModel(filename);
if (md2->model)
+1 -57
View File
@@ -275,13 +275,6 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
return NULL;
retModel = (model_t*)Z_Calloc(sizeof(model_t), ztag, NULL);
//size_t fileLen;
//int i, j;
//size_t namelen;
//char *texturefilename;
texPos = strchr(fileName, '/');
if (texPos)
@@ -318,8 +311,6 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
retModel->numMeshes = 1; // MD2 only has one mesh
retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t) * retModel->numMeshes, ztag, NULL);
retModel->meshes[0].numFrames = header->numFrames;
// const float WUNITS = 1.0f;
// float dataScale = WUNITS;
// Tris and ST are simple structures that can be straight-copied
tris = (md2triangle_t*)&buffer[header->offsetTris];
@@ -355,47 +346,6 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
retModel->materials[t].specular[3] = 1.0f;
retModel->materials[t].shininess = 0.0f;
retModel->materials[t].spheremap = false;
/* retModel->materials[t].texture = Texture::ReadTexture((char*)texturefilename, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, texturefilename);
size_t len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[t].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[0].numTriangles = header->numTris;
@@ -425,15 +375,11 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].tinyframes[i].vertices = (short*)Z_Malloc(sizeof(short) * 3 * header->numXYZ, ztag, NULL);
retModel->meshes[0].tinyframes[i].normals = (char*)Z_Malloc(sizeof(char) * 3 * header->numXYZ, ztag, NULL);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].tinyframes[i].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*header->numVerts, ztag);
retModel->meshes[0].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * header->numTris, ztag, NULL);
vertptr = retModel->meshes[0].tinyframes[i].vertices;
normptr = retModel->meshes[0].tinyframes[i].normals;
// tanptr = retModel->meshes[0].tinyframes[i].tangents;
retModel->meshes[0].tinyframes[i].material = &retModel->materials[0];
framePtr++; // Advance to vertex list
@@ -509,9 +455,7 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat)
md2frame_t *framePtr = (md2frame_t*)ptr;
retModel->meshes[0].frames[i].normals = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, NULL);
retModel->meshes[0].frames[i].vertices = (float*)Z_Malloc(sizeof(float) * 3 * header->numTris * 3, ztag, NULL);
// if (retModel->materials[0].lightmap)
// retModel->meshes[0].frames[i].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*header->numTris*3, ztag);
//float *vertptr, *normptr;
normptr = (float*)retModel->meshes[0].frames[i].normals;
vertptr = (float*)retModel->meshes[0].frames[i].vertices;
trisPtr = tris;
+1 -79
View File
@@ -243,48 +243,6 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
mdShader[j].name[len-1] = 'z';
mdShader[j].name[len-2] = 'u';
mdShader[j].name[len-3] = 'b';
// Load material
/* retModel->materials[matCount].texture = Texture::ReadTexture(mdShader[j].name, ZT_TEXTURE);
if (!systemSucks)
{
// Check for a normal map...??
char openfilename[1024];
char normalMapName[1024];
strcpy(normalMapName, mdShader[j].name);
len = strlen(normalMapName);
char *ptr = &normalMapName[len];
ptr--; // z
ptr--; // u
ptr--; // b
ptr--; // .
*ptr++ = '_';
*ptr++ = 'n';
*ptr++ = '.';
*ptr++ = 'b';
*ptr++ = 'u';
*ptr++ = 'z';
*ptr++ = '\0';
sprintf(openfilename, "%s/%s", "textures", normalMapName);
// Convert backslashes to forward slashes
for (int k = 0; k < 1024; k++)
{
if (openfilename[k] == '\0')
break;
if (openfilename[k] == '\\')
openfilename[k] = '/';
}
Resource::resource_t *res = Resource::Open(openfilename);
if (res)
{
Resource::Close(res);
retModel->materials[matCount].lightmap = Texture::ReadTexture(normalMapName, ZT_TEXTURE);
}
}*/
}
retModel->meshes[i].numFrames = mdS->numFrames;
@@ -305,19 +263,15 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
{
short *vertptr;
char *normptr;
// char *tanptr;
int k;
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].tinyframes[j].vertices = (short*)Z_Malloc(sizeof(short)*3*mdS->numVerts, ztag, NULL);
retModel->meshes[i].tinyframes[j].normals = (char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag, NULL);
// if (retModel->materials[0].lightmap)
// retModel->meshes[i].tinyframes[j].tangents = (char*)malloc(sizeof(char));//(char*)Z_Malloc(sizeof(char)*3*mdS->numVerts, ztag);
retModel->meshes[i].indices = (unsigned short*)Z_Malloc(sizeof(unsigned short) * 3 * mdS->numTriangles, ztag, NULL);
vertptr = retModel->meshes[i].tinyframes[j].vertices;
normptr = retModel->meshes[i].tinyframes[j].normals;
// tanptr = retModel->meshes[i].tinyframes[j].tangents;
retModel->meshes[i].tinyframes[j].material = &retModel->materials[i];
for (k = 0; k < mdS->numVerts; k++)
@@ -384,8 +338,7 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
md3Vertex *mdV = (md3Vertex*)((char*)mdS + mdS->offsetXYZNormal + (mdS->numVerts*j*sizeof(md3Vertex)));
retModel->meshes[i].frames[j].vertices = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, NULL);
retModel->meshes[i].frames[j].normals = (float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag, NULL);
// if (retModel->materials[i].lightmap)
// retModel->meshes[i].frames[j].tangents = (float*)malloc(sizeof(float));//(float*)Z_Malloc(sizeof(float)*3*mdS->numTriangles*3, ztag);
vertptr = retModel->meshes[i].frames[j].vertices;
normptr = retModel->meshes[i].frames[j].normals;
retModel->meshes[i].frames[j].material = &retModel->materials[i];
@@ -471,37 +424,6 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat)
}
}
}
/*
// Tags?
retModel->numTags = mdh->numTags;
retModel->maxNumFrames = mdh->numFrames;
retModel->tags = (tag_t*)Z_Calloc(sizeof(tag_t) * retModel->numTags * mdh->numFrames, ztag);
md3Tag *mdTag = (md3Tag*)&buffer[mdh->offsetTags];
tag_t *curTag = retModel->tags;
for (i = 0; i < mdh->numFrames; i++)
{
int j;
for (j = 0; j < retModel->numTags; j++, mdTag++)
{
strcpys(curTag->name, mdTag->name, sizeof(curTag->name) / sizeof(char));
curTag->transform.m[0][0] = mdTag->axis[0];
curTag->transform.m[0][1] = mdTag->axis[1];
curTag->transform.m[0][2] = mdTag->axis[2];
curTag->transform.m[1][0] = mdTag->axis[3];
curTag->transform.m[1][1] = mdTag->axis[4];
curTag->transform.m[1][2] = mdTag->axis[5];
curTag->transform.m[2][0] = mdTag->axis[6];
curTag->transform.m[2][1] = mdTag->axis[7];
curTag->transform.m[2][2] = mdTag->axis[8];
curTag->transform.m[3][0] = mdTag->origin[0] * WUNITS;
curTag->transform.m[3][1] = mdTag->origin[1] * WUNITS;
curTag->transform.m[3][2] = mdTag->origin[2] * WUNITS;
curTag->transform.m[3][3] = 1.0f;
Matrix::Rotate(&curTag->transform, 90.0f, &Vector::Xaxis);
curTag++;
}
}*/
free(buffer);
+3
View File
@@ -41,6 +41,9 @@ static struct {
// Water shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER},
// Water refraction shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATERREFRACT_FRAGMENT_SHADER},
// Fog shader
{GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER},
+38 -8
View File
@@ -243,23 +243,30 @@
// Water surface shader
//
// Mostly guesstimated, rather than the rest being built off Software science.
// Still needs to distort things underneath/around the water...
// Still needs to distort things underneath/around the water... // huehueuehuehue
//
// readjusted to match software much more closely
#define GLSL_WATER_CONST \
"const float freq = 0.07;\n" \
"const float amp = 0.07;\n" \
"const float amp_t = 0.025;\n" \
"const float speed = 4.0;\n" \
"const float pi = 3.14159;\n" \
"const float falltresh = 0.007;\n" \
#define GLSL_WATER_TEXEL \
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
"float sdistort = sin(a) * amp;\n" \
"float cdistort = cos(a) * amp;\n" \
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n"
"float falloff = 1.0 / (1.0 + water_z * falltresh);\n" \
"float distort = sin(a) * amp * falloff;\n" \
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - distort, gl_TexCoord[0].t));\n" \
#define GLSL_WATER_FRAGMENT_SHADER \
"#version 120\n" \
GLSL_FLOOR_FUDGES \
"const float freq = 0.025;\n" \
"const float amp = 0.025;\n" \
"const float speed = 2.0;\n" \
"const float pi = 3.14159;\n" \
GLSL_WATER_CONST \
"#ifdef SRB2_PALETTE_RENDERING\n" \
"uniform sampler2D tex;\n" \
"uniform sampler3D palette_lookup_tex;\n" \
@@ -294,6 +301,29 @@
"}\n" \
"#endif\0"
// water refraction stuff
// this is probably complete shit but i dont care
// got the idea for depth testing from https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-refraction.html
#define GLSL_WATERREFRACT_FRAGMENT_SHADER \
"#version 120\n" \
GLSL_WATER_CONST \
"uniform sampler2D scene_tex;\n" \
"uniform sampler2D scene_depth_tex;\n" \
"uniform vec2 scr_resolution;\n" \
"uniform float leveltime;\n" \
"void main(void) {\n" \
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
"float falloff = 1.0 / (1.0 + water_z * falltresh);\n" \
"float distort = sin(a) * amp * falloff;\n" \
"vec2 uv = (gl_FragCoord.xy / scr_resolution) + vec2(distort, distort * 2.0) * 0.04;\n" \
"float scenedepth = texture2D(scene_depth_tex, uv).r;\n" \
"if (scenedepth < gl_FragCoord.z) {\n" \
"discard;\n" \
"}\n" \
"gl_FragColor = texture2D(scene_tex, uv);\n" \
"}\0"
//
// Fog block shader
//
+91
View File
@@ -173,6 +173,15 @@ boolean supportstencil = false;
// can know when the textures aren't there, as textures are always considered resident in their virtual memory
static GLuint screenTextures[NUMSCREENTEXTURES] = {};
// for water refraction
enum
{
SCENE_TEX,
SCENE_DEPTHTEX,
NUMSCENETEXTURES
};
static GLuint sceneTextures[NUMSCENETEXTURES] = {};
#define byte2float(byte) (GLfloat)(byte / 255.0f)
// -----------------+
@@ -723,6 +732,9 @@ typedef enum
gluniform_palette_lookup_tex, // 3d texture containing the rgb->index lookup table
gluniform_lighttable_tex, // 2d texture containing a light table
gluniform_scene_tex,
gluniform_scene_depth_tex,
// misc.
gluniform_leveltime,
@@ -2386,6 +2398,9 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
// misc.
shader->uniforms[gluniform_leveltime] = GETUNI("leveltime");
shader->uniforms[gluniform_scene_tex] = GETUNI("scene_tex");
shader->uniforms[gluniform_scene_depth_tex] = GETUNI("scene_depth_tex");
#undef GETUNI
// set permanent uniform values
@@ -2400,6 +2415,9 @@ static boolean GL_Shader_CompileProgram(gl_shader_t *shader, GLint i)
UNIFORM_1(shader->uniforms[gluniform_palette_lookup_tex], 1, pglUniform1i);
UNIFORM_1(shader->uniforms[gluniform_lighttable_tex], 2, pglUniform1i);
UNIFORM_1(shader->uniforms[gluniform_scene_tex], 4, pglUniform1i);
UNIFORM_1(shader->uniforms[gluniform_scene_depth_tex], 5, pglUniform1i);
// restore gl shader state
pglUseProgram(gl_shaderstate.program);
#undef UNIFORM_1
@@ -2480,6 +2498,24 @@ void GL_DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, F
Clamp2D(GL_TEXTURE_WRAP_T);
}
void GL_DrawWaterPolygon(FOutVector *pOutVerts, FUINT iNumPts)
{
GL_SetShader(HWR_GetShaderFromTarget(SHADER_WATERREFRACT));
pglActiveTexture(GL_TEXTURE4);
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_TEX]);
pglActiveTexture(GL_TEXTURE0);
pglActiveTexture(GL_TEXTURE5);
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_DEPTHTEX]);
pglActiveTexture(GL_TEXTURE0);
GL_PreparePolygon(NULL, PF_NoTexture|PF_Ripple);
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
}
void GL_DrawIndexedTriangles(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, unsigned int *IndexArray)
{
GL_PreparePolygon(pSurf, PolyFlags);
@@ -3384,6 +3420,57 @@ void GL_Framebuffer_Disable(void)
}
#endif
// faster than fbo blitting ig...
// just copies the whole framebuffer as a texture
void GL_CopyMainFramebufferTexture(void)
{
if (!sceneTextures[SCENE_TEX])
{
pglGenTextures(1, &sceneTextures[SCENE_TEX]);
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_TEX]);
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);
Clamp2D(GL_TEXTURE_WRAP_T);
pglBindTexture(GL_TEXTURE_2D, 0);
}
// now copy the whole scene
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_TEX]);
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screen_width, screen_height);
// not sure why, but this is needed
// otherwise bad things happen
tex_downloaded = sceneTextures[SCENE_TEX];
pglBindTexture(GL_TEXTURE_2D, 0);
}
void GL_CopyMainFramebufferDepth(void)
{
if (!sceneTextures[SCENE_DEPTHTEX])
{
pglGenTextures(1, &sceneTextures[SCENE_DEPTHTEX]);
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_DEPTHTEX]);
pglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, screen_width, screen_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 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);
Clamp2D(GL_TEXTURE_WRAP_T);
pglBindTexture(GL_TEXTURE_2D, 0);
}
// and copy the depth from the scene
// we need this for depth testing within the shader
// so we can discard stuff in front of the water
// this aint reflections after all!
pglBindTexture(GL_TEXTURE_2D, sceneTextures[SCENE_DEPTHTEX]);
pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screen_width, screen_height);
pglBindTexture(GL_TEXTURE_2D, 0);
}
static const float defaultscreenVerts[12] =
{
-1.0f, -1.0f, 1.0f,
@@ -3505,6 +3592,10 @@ void GL_FlushScreenTextures(void)
{
pglDeleteTextures(NUMSCREENTEXTURES, screenTextures);
memset(screenTextures, 0, sizeof(screenTextures));
// gotta wipe the scene textures for the water refraction stuff aswell
pglDeleteTextures(NUMSCENETEXTURES, sceneTextures);
memset(sceneTextures, 0, sizeof(sceneTextures));
}
void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags)
+3
View File
@@ -104,6 +104,9 @@ void GL_Framebuffer_Disable(void);
extern int supportFBO;
#endif
void GL_CopyMainFramebufferTexture(void);
void GL_CopyMainFramebufferDepth(void);
// ==========================================================================
// GLOBAL
// ==========================================================================
+10 -8
View File
@@ -135,8 +135,7 @@ HMS_on_read (char *s, size_t _1, size_t n, void *userdata)
return n;
}
static struct HMS_buffer *
HMS_connect (const char *format, ...)
static struct HMS_buffer *HMS_connect(const char *format, ...)
{
va_list ap;
CURL *curl;
@@ -174,7 +173,7 @@ HMS_connect (const char *format, ...)
if (cv_masterserver_token.string && cv_masterserver_token.string[0])
{
quack_token = curl_easy_escape(curl, cv_masterserver_token.string, 0);
token_length = ( sizeof "&token="-1 )+ strlen(quack_token);
token_length = ( sizeof "&token="-1 ) + strlen(quack_token);
}
else
{
@@ -186,27 +185,30 @@ HMS_connect (const char *format, ...)
I_lock_mutex(&hms_api_mutex);
#endif
seek = strlen(hms_api) + 1;/* + '/' */
seek = strlen(hms_api) + 1; /* + '/' */
va_start (ap, format);
url = malloc(seek + vsnprintf(NULL, 0, format, ap) + sizeof HMS_QUERY_VERSION - 1 + token_length + 1);
size_t url_size = (seek + vsnprintf(NULL, 0, format, ap) +
sizeof HMS_QUERY_VERSION - 1 +
token_length + 1);
url = malloc(url_size);
va_end (ap);
sprintf(url, "%s/", hms_api);
snprintf(url, seek + 1, "%s/", hms_api);
#ifdef HAVE_THREADS
I_unlock_mutex(hms_api_mutex);
#endif
va_start (ap, format);
seek += vsprintf(&url[seek], format, ap);
seek += vsnprintf(&url[seek], url_size - seek, format, ap);
va_end (ap);
strcpy(&url[seek], HMS_QUERY_VERSION);
seek += sizeof HMS_QUERY_VERSION - 1;
if (quack_token)
sprintf(&url[seek], "&token=%s", quack_token);
snprintf(&url[seek], url_size - seek, "&token=%s", quack_token);
Printf_url(url);
+12 -11
View File
@@ -154,14 +154,14 @@ void HU_LoadGraphics(void)
for (i = 0; i < HU_FONTSIZE; i++, j++)
{
// cache the heads-up font for entire game execution
sprintf(buffer, "STCFN%.3d", j);
snprintf(buffer, sizeof(buffer), "STCFN%.3d", j);
if (W_CheckNumForName(buffer) == LUMPERROR)
hu_font[i] = NULL;
else
hu_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
// tiny version of the heads-up font
sprintf(buffer, "TNYFN%.3d", j);
snprintf(buffer, sizeof(buffer), "TNYFN%.3d", j);
if (W_CheckNumForName(buffer) == LUMPERROR)
tny_font[i] = NULL;
else
@@ -188,7 +188,7 @@ void HU_LoadGraphics(void)
for (i = 0; i < KART_FONTSIZE; i++, j++)
{
// cache the heads-up font for entire game execution
sprintf(buffer, "MKFNT%.3d", j);
snprintf(buffer, sizeof(buffer), "MKFNT%.3d", j);
if (W_CheckNumForName(buffer) == LUMPERROR)
kart_font[i] = NULL;
else
@@ -199,7 +199,7 @@ void HU_LoadGraphics(void)
j = LT_FONTSTART;
for (i = 0; i < LT_FONTSIZE; i++)
{
sprintf(buffer, "LTFNT%.3d", j);
snprintf(buffer, sizeof(buffer), "LTFNT%.3d", j);
j++;
if (W_CheckNumForName(buffer) == LUMPERROR)
@@ -212,7 +212,7 @@ void HU_LoadGraphics(void)
j = CRED_FONTSTART;
for (i = 0; i < CRED_FONTSIZE; i++)
{
sprintf(buffer, "CRFNT%.3d", j);
snprintf(buffer, sizeof(buffer), "CRFNT%.3d", j);
j++;
if (W_CheckNumForName(buffer) == LUMPERROR)
@@ -224,11 +224,11 @@ void HU_LoadGraphics(void)
// cache numbers too!
for (i = 0; i < 10; i++)
{
sprintf(buffer, "STTNUM%d", i);
snprintf(buffer, sizeof(buffer), "STTNUM%d", i);
tallnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
sprintf(buffer, "PINGN%d", i);
snprintf(buffer, sizeof(buffer), "PINGN%d", i);
pingnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
sprintf(buffer, "OPPRNK0%d", i);
snprintf(buffer, sizeof(buffer), "OPPRNK0%d", i);
ranknum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
@@ -240,7 +240,7 @@ void HU_LoadGraphics(void)
// cache ping gfx:
for (i = 0; i < 5; i++)
{
sprintf(buffer, "PINGGFX%d", i+1);
snprintf(buffer, sizeof(buffer), "PINGGFX%d", i+1);
pinggfx[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
@@ -2830,8 +2830,9 @@ static void HU_DrawRankings(void)
scorelines++;
#if MAXPLAYERS > 16
if (scorelines > 16)
break; //dont draw past bottom of screen, show the best only
// 32 Player TODO: port over and cleanup scoreboard from sat-32p/blankart
if (scorelines >= 16)
break; // dont draw past bottom of screen, show the best only
#endif
}
+15
View File
@@ -237,6 +237,21 @@ char *I_GetUserName(void);
*/
INT32 I_mkdir(const char *dirname, INT32 unixright);
/** \brief Change current working directory
\param path directory path
\return 0 on success, -1 on error
*/
INT32 I_ChDir(const char *path);
/** \brief Get current working directory
\param buf buffer to store path
\param size size of buffer
\return buf on success, NULL on error
*/
char *I_GetCwd(char *buf, size_t size);
/** \brief Find main WAD
\return path to main WAD
*/
+4 -5
View File
@@ -213,7 +213,7 @@ static char *get_WSAErrorStr(int e)
NULL);
if (!buf[0]) // provide a fallback error message if no message is available for some reason
sprintf(buf, "Unknown error");
snprintf(buf, sizeof(buf), "Unknown error");
return buf;
}
@@ -364,12 +364,12 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
if (addr == NULL)
{
sprintf(s, "No address");
snprintf(s, sizeof(s), "No address");
}
else if (inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL)
{
e = errno;
sprintf(s, "Unknown family type, error #%u: %s", e, strerror(e));
snprintf(s, sizeof(s), "Unknown family type, error #%u: %s", e, strerror(e));
}
#ifdef HAVE_IPV6
else if(sk->any.sa_family == AF_INET6)
@@ -416,7 +416,7 @@ static const char *SOCK_GetBanMask(size_t ban)
if (ban >= numbans)
return NULL;
if (sprintf(s,"%d",banned[ban].mask) > 0)
if (snprintf(s, sizeof(s), "%d",banned[ban].mask) > 0)
return s;
return NULL;
@@ -622,7 +622,6 @@ static boolean hole_punch(ssize_t c)
{
return false;
}
}
#endif //ifdef HOLEPUNCH
+40 -19
View File
@@ -388,7 +388,7 @@ static void K_LoadSaturnHUDGraphics(void)
skp_speedpatchesdial[3] = (patch_t *)W_CachePatchName("SP_DFRAC", PU_HUDGFX);
skp_speedpatchesdial[4] = (patch_t *)W_CachePatchName("SP_DPERC", PU_HUDGFX);
sprintf(buffer, "K_DSPNMx");
snprintf(buffer, sizeof(buffer), "K_DSPNMx");
for (i = 0; i < 10; i++)
{
buffer[7] = '0'+(i%10);
@@ -507,7 +507,7 @@ static void K_LoadSaturnHUDGraphics(void)
skp_speedpatchesdialclr[3] = (patch_t *)W_CachePatchName("SC_DFRAC", PU_HUDGFX);
skp_speedpatchesdialclr[4] = (patch_t *)W_CachePatchName("SC_DPERC", PU_HUDGFX);
sprintf(buffer, "K_DSPNCx");
snprintf(buffer, sizeof(buffer), "K_DSPNCx");
for (i = 0; i < 10; i++)
{
buffer[7] = '0'+(i%10);
@@ -677,7 +677,7 @@ void K_LoadKartHUDGraphics(void)
kp_racefinish[5] = (patch_t *)W_CachePatchName("K_2PFINB", PU_HUDGFX);
// Position numbers
sprintf(buffer, "K_POSNxx");
snprintf(buffer, sizeof(buffer), "K_POSNxx");
for (i = 0; i < NUMPOSNUMS; i++)
{
buffer[6] = '0'+i;
@@ -688,14 +688,17 @@ void K_LoadKartHUDGraphics(void)
}
}
sprintf(buffer, "K_POSNWx");
snprintf(buffer, sizeof(buffer), "K_POSNWx");
for (i = 0; i < NUMWINFRAMES; i++)
{
buffer[7] = '0'+i;
kp_winnernum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
sprintf(buffer, "OPPRNKxx");
// 32 player note: there are only 16 of those!
// so slots after this will just be missing patches!
// but keeping like this incase of missed adjustments which might cause crashes otherwise
snprintf(buffer, sizeof(buffer), "OPPRNKxx");
for (i = 0; i <= MAXPLAYERS; i++)
{
buffer[6] = '0'+(i/10);
@@ -703,7 +706,7 @@ void K_LoadKartHUDGraphics(void)
kp_facenum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
sprintf(buffer, "K_CHILIx");
snprintf(buffer, sizeof(buffer), "K_CHILIx");
for (i = 0; i < 8; i++)
{
buffer[7] = '0'+(i+1);
@@ -772,21 +775,21 @@ void K_LoadKartHUDGraphics(void)
kp_kitchensink[1] = (patch_t *)W_CachePatchName("K_ISSINK", PU_HUDGFX);
kp_sadface[1] = (patch_t *)W_CachePatchName("K_ISSAD", PU_HUDGFX);
sprintf(buffer, "K_ITINVx");
snprintf(buffer, sizeof(buffer), "K_ITINVx");
for (i = 0; i < 7; i++)
{
buffer[7] = '1'+i;
kp_invincibility[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
sprintf(buffer, "K_ITORBx");
snprintf(buffer, sizeof(buffer), "K_ITORBx");
for (i = 0; i < 4; i++)
{
buffer[7] = '1'+i;
kp_orbinaut[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
sprintf(buffer, "K_ISINVx");
snprintf(buffer, sizeof(buffer), "K_ISINVx");
for (i = 0; i < 6; i++)
{
buffer[7] = '1'+i;
@@ -794,7 +797,7 @@ void K_LoadKartHUDGraphics(void)
}
// CHECK indicators
sprintf(buffer, "K_CHECKx");
snprintf(buffer, sizeof(buffer), "K_CHECKx");
for (i = 0; i < 6; i++)
{
buffer[7] = '1'+i;
@@ -802,7 +805,7 @@ void K_LoadKartHUDGraphics(void)
}
// Eggman warning numbers
sprintf(buffer, "K_EGGNx");
snprintf(buffer, sizeof(buffer), "K_EGGNx");
for (i = 0; i < 4; i++)
{
buffer[6] = '0'+i;
@@ -815,7 +818,7 @@ void K_LoadKartHUDGraphics(void)
kp_fpview[2] = (patch_t *)W_CachePatchName("VIEWC0E0", PU_HUDGFX);
// Input UI Wheel
sprintf(buffer, "K_WHEELx");
snprintf(buffer, sizeof(buffer), "K_WHEELx");
for (i = 0; i < 5; i++)
{
buffer[7] = '0'+i;
@@ -823,7 +826,7 @@ void K_LoadKartHUDGraphics(void)
}
// HERE COMES A NEW CHALLENGER
sprintf(buffer, "K_CHALxx");
snprintf(buffer, sizeof(buffer), "K_CHALxx");
for (i = 0; i < 25; i++)
{
buffer[6] = '0'+((i+1)/10);
@@ -832,14 +835,14 @@ void K_LoadKartHUDGraphics(void)
}
// Lap start animation
sprintf(buffer, "K_LAP0x");
snprintf(buffer, sizeof(buffer), "K_LAP0x");
for (i = 0; i < 7; i++)
{
buffer[6] = '0'+(i+1);
kp_lapanim_lap[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
sprintf(buffer, "K_LAPFxx");
snprintf(buffer, sizeof(buffer), "K_LAPFxx");
for (i = 0; i < 11; i++)
{
buffer[6] = '0'+((i+1)/10);
@@ -847,7 +850,7 @@ void K_LoadKartHUDGraphics(void)
kp_lapanim_final[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
sprintf(buffer, "K_LAPNxx");
snprintf(buffer, sizeof(buffer), "K_LAPNxx");
for (i = 0; i < 10; i++)
{
buffer[6] = '0'+i;
@@ -858,14 +861,14 @@ void K_LoadKartHUDGraphics(void)
}
}
sprintf(buffer, "K_LAPE0x");
snprintf(buffer, sizeof(buffer), "K_LAPE0x");
for (i = 0; i < 2; i++)
{
buffer[7] = '0'+(i+1);
kp_lapanim_emblem[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
sprintf(buffer, "K_LAPH0x");
snprintf(buffer, sizeof(buffer), "K_LAPH0x");
for (i = 0; i < 3; i++)
{
buffer[7] = '0'+(i+1);
@@ -1974,7 +1977,7 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UI
goto bademblem;
}
snprintf(targettext, 9, "%i'%02i\"%02i",
snprintf(targettext, sizeof(targettext), "%i'%02i\"%02i",
G_TicsToMinutes(timetoreach, false),
G_TicsToSeconds(timetoreach),
G_TicsToCentiseconds(timetoreach));
@@ -2294,6 +2297,11 @@ static boolean K_drawKartPositionFaces(void)
if (pos < 0 || pos > MAXPLAYERS)
pos = 0;
#if MAXPLAYERS > 16
if (pos > 16)
V_DrawPingNum(FACE_X+2, Y+10, V_HUDTRANS|V_SNAPTOLEFT, pos, NULL);
else
#endif
// Draws the little number over the face
V_DrawScaledPatch(FACE_X-5, Y+10, V_HUDTRANS|V_SNAPTOLEFT, kp_facenum[pos]);
}
@@ -2385,6 +2393,12 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
INT32 pos = player->kartstuff[k_position];
if (pos < 0 || pos > MAXPLAYERS)
pos = 0;
#if MAXPLAYERS > 16
if (pos > 16)
V_DrawPingNum(x+2, y+10, 0, pos, NULL);
else
#endif
// Draws the little number over the face
V_DrawScaledPatch(x-5, y+6, 0, kp_facenum[pos]);
}
@@ -3581,6 +3595,10 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags)
#endif
skin = K_GetMobjSkin(mo);
if (!skin)
return;
minimaphead = (skinlocal ? localfacemmapprefix : facemmapprefix)[K_GetMobjSkinNum(skin, skinlocal)];
if (minimaphead == NULL)
@@ -3784,6 +3802,9 @@ static void K_drawKartMinimap(void)
mobj_t *mobj = players[localplayers[i]].mo;
if (!mobj)
continue;
// dont draw for no contestants
boolean playertimedout = (mobj->health <= 0 && players[localplayers[i]].pflags & PF_TIMEOVER);
+6
View File
@@ -1033,6 +1033,12 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush)
}
}
#if MAXPLAYERS > 16
// courtesy of fickle from 1.1 battleroyale
// battleroyale: limit how much items will scale to try to prevent shit-tier items in shit-huge netames
pingame = min(pingame, 12);
#endif
if (first != -1 && second != -1) // calculate 2nd's distance from 1st, for SPB
{
secondist = P_AproxDistance(P_AproxDistance(players[first].mo->x - players[second].mo->x,
+2
View File
@@ -3087,6 +3087,8 @@ static int lib_gPlayerDeviceRumble(lua_State *L)
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (demo.playback) return 0;
pnum = P_GetLocalPlayerNumForPlayer(player);
// Not a local player
+56 -11
View File
@@ -25,6 +25,7 @@
#include "lua_libs.h"
#include "lua_hook.h"
#include "lua_hud.h" // hud_running errors
#include "lua_profile.h"
/* =========================================================================
ABSTRACTION
@@ -445,11 +446,54 @@ FUNCINLINE static ATTRINLINE void get_hook_from_table(Hook_State *hook, int n)
lua_getref(gL, hookRefs[hook->id]);
}
static int pcall(Hook_State *hook)
{
return lua_pcall(gL, hook->values, hook->results, EINDEX);
}
static const char *hook_name(Hook_State *hook)
{
if (hud_running)
{
return hudHookNames[hook->hook_type];
}
else if (hook->string)
{
return stringHookNames[hook->hook_type];
}
//else if (hook->mobj_type > 0)
else if (hook->mobj_type != NONMOHOOK)
{
return mobjHookNames[hook->hook_type];
}
else
{
return hookNames[hook->hook_type];
}
}
static int pcall_timed_or_untimed(Hook_State *hook)
{
if (!hud_running && cv_lua_profile.value > 0)
{
lua_timer_t *timer = LUA_BeginFunctionTimer(gL, -1 - hook->values, hook_name(hook));
int k = pcall(hook);
LUA_EndFunctionTimer(timer);
return k;
}
else
{
return pcall(hook);
}
}
static int call_single_hook_no_copy(Hook_State *hook)
{
hook_important = hook->important;
if (lua_pcall(gL, hook->values, hook->results, EINDEX) == 0)
//if (lua_pcall(gL, hook->values, hook->results, EINDEX) == 0)
if (pcall_timed_or_untimed(hook) == 0)
{
if (hook->results > 0)
{
@@ -535,16 +579,16 @@ FUNCINLINE static ATTRINLINE int call_mobj_type_hooks(Hook_State *hook, mobjtype
static UINT8 seen = 0; // so we dont have to check all this shit constantly
int numCalls = call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]);
if (!seen && numCalls > 0 && mobj_type == MT_NULL && (
hook->hook_type == MOBJ_HOOK(MobjThinker )
if (!seen && numCalls > 0 && mobj_type == MT_NULL &&
( hook->hook_type == MOBJ_HOOK(MobjThinker )
|| hook->hook_type == MOBJ_HOOK(MobjCollide )
|| hook->hook_type == MOBJ_HOOK(MobjMoveCollide)
|| hook->hook_type == MOBJ_HOOK(MobjFuse )
|| hook->hook_type == MOBJ_HOOK(MobjThinker )
|| hook->hook_type == MOBJ_HOOK(BossThinker )
))
{
seen = 1;
CONS_Alert(
CONS_WARNING, "%s\n", va(
"%s hooks not attached to a specific mobj type may cause performance issues!",
@@ -566,12 +610,10 @@ FUNCINLINE static ATTRINLINE int call_mobj_type_hooks(Hook_State *hook, mobjtype
return numCalls;
}
/*
FUNCINLINE static ATTRINLINE int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type)
/*FUNCINLINE static ATTRINLINE int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type)
{
return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]);
}
*/
}*/
static int call_hooks
(
@@ -760,7 +802,7 @@ static void hook_think_frame(int type)
const hook_t * map = &hookIds[type];
int k;
const boolean perfstats = (cv_perfstats.value >= 3);
const boolean perfstats = (cv_perfstats.value >= PS_THINKFRAME);
if (prepare_hook(&hook, 0, type))
{
@@ -856,7 +898,7 @@ int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT3
int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
return damage_hook(target, inflictor, source, damage,
MOBJ_HOOK(MobjDamage), res_true);
MOBJ_HOOK(MobjDamage), res_true);
}
int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source)
@@ -945,7 +987,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
{
Hook_State hook = {};
if (prepare_string_hook
(&hook, 0, STRING_HOOK(LinedefExecute), line->text))
(&hook, 0, STRING_HOOK(LinedefExecute), line->text))
{
LUA_PushUserdata(gL, line, META_LINE);
LUA_PushUserdata(gL, mo, META_MOBJ);
@@ -1018,6 +1060,9 @@ void LUA_HookNetArchive(lua_CFunction archFunc, savebuffer_t *save)
lua_pushcclosure(gL, archFunc, 2);
// stack: tables, savebuffer_t, archFunc
// Manually set the hook's variables here since we don't call prepare_hook
hook.hook_type = HOOK(NetVars);
hook.mobj_type = NONMOHOOK; // Force mobj_type to be NONMOHOOK so the mobj_type check get skipped
init_hook_call(&hook, 0, res_none);
call_mapped(&hook, map);
+5 -1
View File
@@ -22,7 +22,8 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // cmd errors
#include "lua_hook.h" // hook_cmd_running errors
#include "lua_profile.h"
boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor);
state_t *astate = NULL;
@@ -110,7 +111,10 @@ static void A_Lua(mobj_t *actor)
LUA_PushUserdata(gL, actor, META_MOBJ);
lua_pushinteger(gL, var1);
lua_pushinteger(gL, var2);
lua_timer_t *timer = LUA_BeginFunctionTimer(gL, -4, "A_Lua");
LUA_Call(gL, 3, 0, 1);
LUA_EndFunctionTimer(timer);
lua_pop(gL, 1); // pop error handler
+264
View File
@@ -0,0 +1,264 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by James Robert Roman
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#include "screen.h"
#include <algorithm>
#include <cstddef>
#include <unordered_map>
#include <string>
#include <string_view>
#include <vector>
extern "C" {
#include "blua/lua.h"
};
#include "v_video.h"
#include "command.h"
#include "doomtype.h"
#include "i_system.h"
#include "lua_profile.h"
#include "m_perfstats.h"
extern "C" consvar_t cv_lua_profile;
namespace
{
precise_t g_time_reference;
int g_tics_counted;
double g_running_tic_time;
double g_avg_tic_time;
bool g_invalid;
}; // namespace
struct lua_timer_t
{
struct Stat
{
double calls = 0;
double time = 0.0;
};
Stat running, avg;
};
namespace
{
std::unordered_map<std::string, lua_timer_t> g_tic_timers;
}; // namespace
lua_timer_t* LUA_BeginFunctionTimer(lua_State* L, int fn_idx, const char* name)
{
lua_Debug ar;
lua_pushvalue(L, fn_idx);
lua_getinfo(L, ">S", &ar);
auto label = [&]
{
using sv = std::string_view;
sv view{ar.source};
switch (view.front())
{
case '@': // file
if (std::size_t p = view.rfind('/'); p != sv::npos) // lump or base
{
return view.substr(p + 1);
}
break;
case '=': // ??
view.remove_prefix(1);
break;
}
return view;
};
// i sure hope this std::string mess is fine...
auto [it, ins] = g_tic_timers.try_emplace(std::string(va("%s:%d (%s)", std::string(label()).c_str(), ar.linedefined, name)));
auto& [key, timer] = *it;
g_time_reference = I_GetPreciseTime();
return &timer;
}
void LUA_EndFunctionTimer(lua_timer_t* timer)
{
precise_t t = I_GetPreciseTime() - g_time_reference;
double precision = I_GetPrecisePrecision();
timer->running.time += t / precision;
timer->running.calls += 1.0;
}
void LUA_ResetTicTimers(void)
{
if (cv_lua_profile.value <= 0)
{
return;
}
if (g_tics_counted < cv_lua_profile.value)
{
g_tics_counted++;
double precision = I_GetPrecisePrecision();
g_running_tic_time += ps_prevtictime.value.p / precision;
}
else
{
double counted = g_tics_counted;
for (auto& [key, timer] : g_tic_timers)
{
timer.avg = {timer.running.calls / counted, timer.running.time / counted};
timer.running = {};
}
g_avg_tic_time = g_running_tic_time / counted;
g_running_tic_time = 0.0;
g_tics_counted = 1;
g_invalid = false;
}
}
void LUA_RenderTimers(void)
{
constexpr int kRowHeight = 4;
float row_y = kRowHeight;
// pretty much what the whole srb2::Draw does lol
auto draw_row = [](float x, float y, INT32 flags, const char *str)
{
V_DrawSmallStringAtFixed(
FloatToFixed(x),
FloatToFixed(y),
V_MONOSPACE|V_ALLOWLOWERCASE|flags,
str
);
};
draw_row(0.f, 0.f, 0, va("-- AVERAGES PER TIC (over %d tics) --", cv_lua_profile.value));
if (g_invalid)
{
draw_row(0.f, row_y, V_GRAYMAP, " <Data pending>");
return;
}
std::vector<decltype(g_tic_timers)::iterator> view;
view.reserve(g_tic_timers.size());
auto color_flag = [](double t)
{
if (t < 10.0)
{
return V_GRAYMAP;
}
else if (t >= 100.0)
{
return V_YELLOWMAP;
}
else
{
return 0;
}
};
{
double cum = 0.0;
for (auto it = g_tic_timers.begin(); it != g_tic_timers.end(); ++it)
{
auto& [key, timer] = *it;
cum += timer.avg.time;
if (timer.avg.time > 0.0)
{
view.push_back(it);
}
}
{
const INT32 tally_flags = color_flag(cum * 1'000'000.0);
draw_row(0.f, row_y, tally_flags, va("%8.2f us - TOTAL", cum * 1'000'000.0));
draw_row(0.f, row_y + kRowHeight, tally_flags, va("%8.2f ms", cum * 1000.0));
// dont need to show this if we didnt capture over time
// this would just show nan or inf anyways
if (std::fpclassify(g_avg_tic_time) != FP_ZERO)
{
draw_row(0.f, row_y + kRowHeight * 2, tally_flags, va(
"%8.2f%% overhead (%.2f / %.2f) <-- not counting rendering time",
(cum / g_avg_tic_time) * 100.0,
(cum * (double)TICRATE),
(g_avg_tic_time * (double)TICRATE)
));
}
}
row_y += kRowHeight * 4;
}
std::sort(
view.rbegin(),
view.rend(),
[](auto a, auto b)
{
auto& [k1, t1] = *a;
auto& [k2, t2] = *b;
return t1.avg.time < t2.avg.time;
}
);
for (auto it : view)
{
auto& [key, timer] = *it;
double t = timer.avg.time * 1'000'000.0;
draw_row(0.f, row_y, color_flag(t), va(
"%8.2f us %8.2f calls - %s",
t,
timer.avg.calls,
key.c_str()
));
row_y += kRowHeight;
// FIXME this is all ugly and sucks
if (row_y >= BASEVIDHEIGHT)
break;
}
}
extern "C" void lua_profile_OnChange(void)
{
g_invalid = true;
if (cv_lua_profile.value == 0)
{
g_tic_timers = {};
}
}
+38
View File
@@ -0,0 +1,38 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by James Robert Roman
// Copyright (C) 2025 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
#ifndef lua_profile_h
#define lua_profile_h
#include "blua/lua.h"
#include "doomtype.h"
//#include "typedef.h"
#ifdef __cplusplus
extern "C" {
#endif
struct lua_timer_t;
typedef struct lua_timer_t lua_timer_t;
void LUA_ResetTicTimers(void);
lua_timer_t *LUA_BeginFunctionTimer(lua_State *L, int fn_idx, const char *name);
void LUA_EndFunctionTimer(lua_timer_t *timer);
void LUA_RenderTimers(void);
void lua_profile_OnChange(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif/*lua_profile_h*/
+6 -5
View File
@@ -277,20 +277,19 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
if (wadfiles[wad]->type == RET_LUA)
{
name = malloc(len+1);
strcpy(name, wadfiles[wad]->filename);
name = malloc(len + 1);
snprintf(name, len + 1, "%s", wadfiles[wad]->filename);
}
else // If it's not a .lua file, copy the lump name in too.
{
lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump];
len += 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
name = malloc(len+1);
name = malloc(len + 1);
if (!name)
I_Error("LUA_LoadLump: Out of memory!\n");
sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->fullname);
name[len] = '\0';
snprintf(name, len + 1, "%s|%s", wadfiles[wad]->filename, lump_p->fullname);
}
LUA_LoadFile(&f, name); // actually load file!
@@ -592,6 +591,7 @@ void LUA_InvalidateLevel(void)
for (i = 0; i < numsubsectors; i++)
LUA_InvalidateUserdata(&subsectors[i]);
for (i = 0; i < numsectors; i++)
{
LUA_InvalidateUserdata(&sectors[i]);
@@ -612,6 +612,7 @@ void LUA_InvalidateLevel(void)
for (i = 0; i < numsides; i++)
LUA_InvalidateUserdata(&sides[i]);
for (i = 0; i < numvertexes; i++)
LUA_InvalidateUserdata(&vertexes[i]);
+1 -1
View File
@@ -11,7 +11,7 @@
#include "m_curl.h"
#include "doomtype.h"
#include "i_system.h" // I_OutputMsg
#include "doomdef.h" // I_OutputMsg
#include "m_argv.h" // M_CheckParm, M_GetNextParm
static boolean curl_args_init = false;
+24 -20
View File
@@ -616,7 +616,7 @@ void Nextmap_OnChange(void)
if (!gpath)
return;
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
snprintf(gpath, glen, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
CV_StealthSetValue(&cv_dummystaff, 0);
@@ -735,7 +735,7 @@ static void Dummystaff_OnChange(void)
while (*temp)
temp++;
sprintf(temp, " - %d", cv_dummystaff.value);
snprintf(temp, sizeof(dummystaffname) - (size_t)(temp - dummystaffname), " - %d", cv_dummystaff.value);
}
}
@@ -825,7 +825,8 @@ static void M_ChangeCvar(INT32 choice)
float increment;
increment = FIXED_TO_FLOAT(cv->value)+(choice)*((currentMenu->menuitems[itemOn].status & IT_CV_BIGFLOAT) ? 0.5f : (1.0f/16.0f));
sprintf(s,"%ld%s",(long)increment,M_Ftrim(increment));
snprintf(s, sizeof(s), "%ld%s", (long)increment, M_Ftrim(increment));
CV_Set(cv, s);
}
else
@@ -4185,12 +4186,12 @@ static void PrepReplayList(boolean reset)
if (dirmenu[i][DIR_TYPE] == EXT_UP)
{
demolist_all[i].type = MD_SUBDIR;
sprintf(demolist_all[i].title, "UP");
snprintf(demolist_all[i].title, sizeof(demolist_all[i].title), "UP");
}
else if (dirmenu[i][DIR_TYPE] == EXT_FOLDER)
{
demolist_all[i].type = MD_SUBDIR;
strncpy(demolist_all[i].title, dirmenu[i] + DIR_STRING, 64);
snprintf(demolist_all[i].title, sizeof(demolist_all[i].title), "%s", dirmenu[i] + DIR_STRING);
}
else
{
@@ -4198,7 +4199,7 @@ static void PrepReplayList(boolean reset)
snprintf(demolist_all[i].filepath, sizeof(demolist_all[i].filepath),
// 255 = UINT8 limit. dirmenu entries are restricted to this length (see DIR_LEN).
"%s%.255s", menupath, dirmenu[i] + DIR_STRING);
sprintf(demolist_all[i].title, ".....");
snprintf(demolist_all[i].title, sizeof(demolist_all[i].title), ".....");
}
}
@@ -5766,7 +5767,8 @@ static void M_DrawMusicTest(void)
x = 24;
y = 64;
if (renderisnewtic) st_musictime++;
if (renderisnewtic)
st_musictime++;
while (t <= b)
{
@@ -5775,11 +5777,11 @@ static void M_DrawMusicTest(void)
{
const musicdef_t *def = S_GetMusicCredit(t);
const size_t MAXLENGTH = 34;
const char *songname = def->title[0] ? def->title : def->source;
size_t namelength = strlen(songname);
#define MAXLENGTH 34
char buf[MAXLENGTH+1];
if (t == st_sel && namelength > MAXLENGTH)
@@ -5788,11 +5790,14 @@ static void M_DrawMusicTest(void)
strlcpy(buf, songname, MAXLENGTH);
V_DrawString(x, y, (t == st_sel ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE|V_MONOSPACE, buf);
if (curplaying == def)
{
V_DrawFill(20+280-9, y-4, 8, 16, 230);
}
#undef MAXLENGTH
}
t++;
y += 16;
}
@@ -5979,7 +5984,8 @@ static void M_DrawStatsMaps(void)
V_DrawString(20, 42, highlightflags|MENUCAPS, "Combined time records:");
sprintf(beststr, "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime));
snprintf(beststr, sizeof(beststr), "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime));
V_DrawRightAlignedString(BASEVIDWIDTH-16, 42, (mapsunfinished ? warningflags : 0), beststr);
if (mapsunfinished)
@@ -7146,7 +7152,7 @@ static void M_CheckMODVersion(int id)
if (updatecheck)
{
sprintf(updatestring, UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck);
snprintf(updatestring, sizeof(updatestring), UPDATE_ALERT_STRING, VERSIONSTRING, updatecheck);
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
@@ -7644,11 +7650,8 @@ static void M_DrawMPMainMenu(void)
// use generic drawer for cursor, items and title
M_DrawGenericMenu();
#if MAXPLAYERS != 16
Update the maxplayers label...
#endif
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+MP_MainMenu[4].alphaKey,
((itemOn == 4) ? highlightflags : 0)|MENUCAPS, "(2-16 Players)");
((itemOn == 4) ? highlightflags : 0)|MENUCAPS, va("(2-%d Players)", MAXPLAYERS));
V_DrawRightAlignedString(BASEVIDWIDTH-x, y+MP_MainMenu[5].alphaKey,
((itemOn == 5) ? highlightflags : 0)|MENUCAPS,
@@ -9598,11 +9601,13 @@ static void M_ChangecontrolResponse(event_t *ev)
menu_t *prev = currentMenu->prevMenu;
if (controltochange == gc_pause)
sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nyou may select another key. \n\nHit another key for\n%s\nESC for Cancel"),
controltochangetext);
{
snprintf(tmp, sizeof(tmp), M_GetText("The \x82Pause Key \x80is enabled, but \nyou may select another key. \n\nHit another key for\n%s\nESC for Cancel"), controltochangetext);
}
else
sprintf(tmp, M_GetText("The \x82Pause Key \x80is enabled, but \nit is not configurable. \n\nHit another key for\n%s\nESC for Cancel"),
controltochangetext);
{
snprintf(tmp, sizeof(tmp), M_GetText("The \x82Pause Key \x80is enabled, but \nit is not configurable. \n\nHit another key for\n%s\nESC for Cancel"), controltochangetext);
}
M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER);
currentMenu->prevMenu = prev;
@@ -9623,8 +9628,7 @@ static void M_ChangeControl(INT32 choice)
static char tmp[68];
controltochange = currentMenu->menuitems[choice].alphaKey;
sprintf(tmp, M_GetText("Hit the new key for\n%s\nESC for Cancel"),
currentMenu->menuitems[choice].text);
snprintf(tmp, sizeof(tmp), M_GetText("Hit the new key for\n%s\nESC for Cancel"), currentMenu->menuitems[choice].text);
strlcpy(controltochangetext, currentMenu->menuitems[choice].text, 33);
M_StartMessage(tmp, M_ChangecontrolResponse, MM_EVENTHANDLER);
+19 -18
View File
@@ -515,8 +515,8 @@ static boolean M_BackupConfig(const char *filename)
{
char backupfile[MAX_WADPATH+4];
snprintf(backupfile, sizeof backupfile, "%s.bak", filename);
backupfile[sizeof backupfile - 1] = '\0';
snprintf(backupfile, sizeof(backupfile), "%s.bak", filename);
backupfile[sizeof(backupfile) - 1] = '\0';
FILE *config = fopen(filename, "r");
@@ -766,27 +766,27 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png
}
if (gamestate == GS_LEVEL)
snprintf(maptext, 8, "%s", G_BuildMapName(gamemap));
snprintf(maptext, sizeof(maptext), "%s", G_BuildMapName(gamemap));
else
snprintf(maptext, 8, "Unknown");
snprintf(maptext, sizeof(maptext), "Unknown");
if (gamestate == GS_LEVEL && mapheaderinfo[gamemap-1]->lvlttl[0] != '\0')
snprintf(lvlttltext, 48, "%s%s%s",
snprintf(lvlttltext, sizeof(lvlttltext), "%s%s%s",
mapheaderinfo[gamemap-1]->lvlttl,
(strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) ? va(" %s",mapheaderinfo[gamemap-1]->zonttl) : // SRB2kart
((mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE"),
(strlen(mapheaderinfo[gamemap-1]->actnum) > 0) ? va(" %s",mapheaderinfo[gamemap-1]->actnum) : "");
else
snprintf(lvlttltext, 48, "Unknown");
snprintf(lvlttltext, sizeof(lvlttltext), "Unknown");
if (gamestate == GS_LEVEL && players[displayplayers[0]].mo)
snprintf(locationtxt, 40, "X:%d Y:%d Z:%d A:%d",
snprintf(locationtxt, sizeof(locationtxt), "X:%d Y:%d Z:%d A:%d",
players[displayplayers[0]].mo->x>>FRACBITS,
players[displayplayers[0]].mo->y>>FRACBITS,
players[displayplayers[0]].mo->z>>FRACBITS,
FixedInt(AngleFixed(players[displayplayers[0]].mo->angle)));
else
snprintf(locationtxt, 40, "Unknown");
snprintf(locationtxt, sizeof(locationtxt), "Unknown");
memset(png_infotext, 0x00, sizeof(png_infotext));
@@ -1253,7 +1253,6 @@ boolean M_ScreenshotResponder(event_t *ev)
return true;
}
void M_ScrollString(const char name[], size_t len, char result[], size_t maxlen, tic_t timer)
{
// How much should we scroll. Not sure why +1 is needed, but without it this function skips 2
@@ -1261,7 +1260,7 @@ void M_ScrollString(const char name[], size_t len, char result[], size_t maxlen,
const size_t amount = len - maxlen + 1;
// Note: anything above 17 will cause zero division
const size_t MAXSPEED = 6;
static const size_t MAXSPEED = 6;
const tic_t t = timer / (35/min(amount, MAXSPEED));
const size_t state = (t / amount) % 4;
@@ -1296,7 +1295,7 @@ void M_ScrollString(const char name[], size_t len, char result[], size_t maxlen,
}
// Technically not necessary, since it gets set again after function call, but just in case
result[maxlen] = 0;
result[maxlen-1] = '\0';
}
void M_MinimapGenerate(void)
@@ -1394,7 +1393,7 @@ char *va(const char *format, ...)
static char string[1024];
va_start(argptr, format);
vsnprintf(string, 1024, format, argptr);
vsnprintf(string, sizeof(string), format, argptr);
va_end(argptr);
return string;
@@ -1708,7 +1707,7 @@ const char * M_Ftrim(double f)
int i;
/* I know I said it's the default, but just in case... */
sprintf(dig, "%.6f", fabs(modf(f, &f)));
snprintf(dig, sizeof(dig), "%.6f", fabs(modf(f, &f)));
/* trim trailing zeroes */
for (i = strlen(dig)-1; dig[i] == '0'; --i)
@@ -1736,6 +1735,7 @@ UINT8 M_CountBits(UINT32 num, UINT8 size)
const char *GetRevisionString(void)
{
static char rev[9] = {0};
if (rev[0])
return rev;
@@ -1743,6 +1743,7 @@ const char *GetRevisionString(void)
strncpy(rev, comprevision, 7);
else
snprintf(rev, 7, "r%s", comprevision);
rev[7] = '\0';
return rev;
@@ -1814,35 +1815,35 @@ TMatrix *RotateZMatrix(angle_t rad)
char *sizeu1(size_t num)
{
static char sizeu1_buf[28];
sprintf(sizeu1_buf, "%"PRIdS, num);
snprintf(sizeu1_buf, sizeof(sizeu1_buf), "%" PRIdS, num);
return sizeu1_buf;
}
char *sizeu2(size_t num)
{
static char sizeu2_buf[28];
sprintf(sizeu2_buf, "%"PRIdS, num);
snprintf(sizeu2_buf, sizeof(sizeu2_buf), "%" PRIdS, num);
return sizeu2_buf;
}
char *sizeu3(size_t num)
{
static char sizeu3_buf[28];
sprintf(sizeu3_buf, "%"PRIdS, num);
snprintf(sizeu3_buf, sizeof(sizeu3_buf), "%" PRIdS, num);
return sizeu3_buf;
}
char *sizeu4(size_t num)
{
static char sizeu4_buf[28];
sprintf(sizeu4_buf, "%"PRIdS, num);
snprintf(sizeu4_buf, sizeof(sizeu4_buf), "%" PRIdS, num);
return sizeu4_buf;
}
char *sizeu5(size_t num)
{
static char sizeu5_buf[28];
sprintf(sizeu5_buf, "%"PRIdS, num);
snprintf(sizeu5_buf, sizeof(sizeu5_buf), "%" PRIdS, num);
return sizeu5_buf;
}
+44 -56
View File
@@ -47,6 +47,7 @@ struct perfstatrow {
static ps_metric_t ps_frametime = {0};
ps_metric_t ps_tictime = {0};
ps_metric_t ps_prevtictime = {0};
ps_metric_t ps_playerthink_time = {0};
ps_metric_t ps_thinkertime = {0};
@@ -97,6 +98,7 @@ perfstatrow_t rendertime_rows[] = {
{" sprdraw", " Sprite render: ", &ps_hw_spritedrawtime, PS_TIME|PS_LEVEL|PS_HW},
{" nodesrt", " Drwnode sort: ", &ps_hw_nodesorttime, PS_TIME|PS_LEVEL|PS_HW},
{" nodedrw", " Drwnode render:", &ps_hw_nodedrawtime, PS_TIME|PS_LEVEL|PS_HW},
{" wtrdrw", " Water render: ", &ps_hw_waterdrawtime, PS_TIME|PS_LEVEL|PS_HW},
{" other ", " Other: ", &ps_otherrendertime, PS_TIME|PS_LEVEL|PS_HW},
#endif
@@ -168,14 +170,14 @@ perfstatrow_t gamelogic_rows[] = {
};
perfstatrow_t thinkercount_rows[] = {
{"thnkers", "Thinkers: ", &ps_thinkercount, PS_LEVEL},
{" mobjs ", " Mobjs: ", &ps_mobjcount, PS_LEVEL},
{"thnkers" , "Thinkers: ", &ps_thinkercount, PS_LEVEL},
{" mobjs " , " Mobjs: ", &ps_mobjcount, PS_LEVEL},
{" regular", " Regular: ", &ps_regularcount, PS_LEVEL},
{" scenery", " Scenery: ", &ps_scenerycount, PS_LEVEL},
{" nothink", " Nothink: ", &ps_nothinkcount, PS_HIDE_ZERO|PS_LEVEL},
{" precip ", " Precipitation: ", &ps_precipcount, PS_LEVEL},
{" other ", " Other: ", &ps_otherthcount, PS_LEVEL},
{" remove ", " Pending removal:", &ps_removecount, PS_LEVEL},
{" precip " , " Precipitation: ", &ps_precipcount, PS_LEVEL},
{" other " , " Other: ", &ps_otherthcount, PS_LEVEL},
{" remove " , " Pending removal:", &ps_removecount, PS_LEVEL},
{}
};
@@ -535,6 +537,7 @@ static void PS_UpdateFrameStats(void)
ps_skyboxtime.value.p +
ps_hw_nodesorttime.value.p +
ps_hw_nodedrawtime.value.p +
ps_hw_waterdrawtime.value.p +
ps_hw_spritesorttime.value.p +
ps_hw_spritedrawtime.value.p;
@@ -605,7 +608,9 @@ static void PS_CountThinkers(void)
else if (thinker->function == (actionf_p1)P_MobjThinker)
{
mobj_t *mobj = (mobj_t*)thinker;
ps_mobjcount.value.i++;
if (mobj->flags & MF_NOTHINK)
ps_nothinkcount.value.i++;
else if (mobj->flags & MF_SCENERY)
@@ -624,49 +629,17 @@ static void PS_CountThinkers(void)
ps_precipcount.value.i++;
}
/*for (i = 0; i < NUM_THINKERLISTS; i++)
{
for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next)
{
ps_thinkercount.value.i++;
if (thinker->function == (actionf_p1)P_RemoveThinkerDelayed)
ps_removecount.value.i++;
else if (i == THINK_POLYOBJ)
ps_polythcount.value.i++;
else if (i == THINK_MAIN)
ps_mainthcount.value.i++;
else if (i == THINK_MOBJ)
{
if (thinker->function == (actionf_p1)P_MobjThinker)
{
mobj_t *mobj = (mobj_t*)thinker;
ps_mobjcount.value.i++;
if (mobj->flags & MF_NOTHINK)
ps_nothinkcount.value.i++;
else if (mobj->flags & MF_SCENERY)
ps_scenerycount.value.i++;
else
ps_regularcount.value.i++;
}
}
else if (i == THINK_DYNSLOPE)
ps_dynslopethcount.value.i++;
else if (i == THINK_PRECIP)
ps_precipcount.value.i++;
}
}*/
}
// Update all metrics that are calculated on every tick.
void PS_UpdateTickStats(void)
{
if (cv_perfstats.value == 1 && cv_ps_samplesize.value > 1)
if (cv_perfstats.value == PS_RENDER && cv_ps_samplesize.value > 1)
{
PS_UpdateRowHistories(gamelogicbrief_row, false);
}
if (cv_perfstats.value == 2)
if (cv_perfstats.value == PS_LOGIC)
{
if (PS_IsLevelActive())
{
@@ -691,25 +664,25 @@ void PS_UpdateTickStats(void)
if (cv_ps_samplesize.value > 1)
{
if (cv_perfstats.value >= 3 && PS_IsLevelActive())
if (cv_perfstats.value >= PS_THINKFRAME && PS_IsLevelActive())
{
int i;
switch (cv_perfstats.value)
{
case 3:
case PS_THINKFRAME:
for (i = 0; i < thinkframe_hooks_length; i++)
{
PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false);
}
break;
case 4:
case PS_PRETHINKFRAME:
for (i = 0; i < prethinkframe_hooks_length; i++)
{
PS_UpdateMetricHistory(&prethinkframe_hooks[i].time_taken, true, false);
}
break;
case 5:
case PS_POSTTHINKFRAME:
for (i = 0; i < postthinkframe_hooks_length; i++)
{
PS_UpdateMetricHistory(&postthinkframe_hooks[i].time_taken, true, false);
@@ -719,6 +692,7 @@ void PS_UpdateTickStats(void)
break;
}
}
if (cv_perfstats.value)
{
ps_tick_index++;
@@ -749,7 +723,7 @@ static void PS_DrawDescriptorHeader(void)
int samples_left = max(ps_frame_samples_left, ps_tick_samples_left);
int x, y;
if (cv_perfstats.value >= 3)
if (cv_perfstats.value >= PS_THINKFRAME)
{
x = 2;
y = 0;
@@ -865,20 +839,19 @@ static void draw_think_frame_stats(int hook_length, ps_hookinfo_t *hook)
last_mod_name[0] = '\0';
INT32 total = 0;
//Decide page length based and drawn text on choosen thinker type
// Decide page length based and drawn text on choosen thinker type
switch (cv_perfstats.value)
{
case 3:
case PS_THINKFRAME:
{
maxpage = thinkframe_hooks_length/PAGE_ENTRIES + 1;
page = max(1, min(cv_ps_thinkframe_page.value, maxpage));
pagestart = min((page - 1)*PAGE_ENTRIES, thinkframe_hooks_length);
pageend = min(pagestart + PAGE_ENTRIES, thinkframe_hooks_length);
V_DrawSmallString(MAX_X-50, MAX_Y+2*HEIGHT, V_MONOSPACE | V_GREENMAP, "ThinkFrame");
}
break;
case 4:
case PS_PRETHINKFRAME:
{
maxpage = prethinkframe_hooks_length/PAGE_ENTRIES + 1;
page = max(1, min(cv_ps_thinkframe_page.value, maxpage));
@@ -887,7 +860,7 @@ static void draw_think_frame_stats(int hook_length, ps_hookinfo_t *hook)
V_DrawSmallString(MAX_X-60, MAX_Y+2*HEIGHT, V_MONOSPACE | V_GREENMAP, "PreThinkFrame");
}
break;
case 5:
case PS_POSTTHINKFRAME:
{
maxpage = postthinkframe_hooks_length/PAGE_ENTRIES + 1;
page = max(1, min(cv_ps_thinkframe_page.value, maxpage));
@@ -975,7 +948,22 @@ static void draw_think_frame_stats(int hook_length, ps_hookinfo_t *hook)
void PS_ThinkFrame_Page_OnChange(void)
{
int maxpage = thinkframe_hooks_length/PAGE_ENTRIES + 1;
int maxpage = 0;
switch (cv_perfstats.value)
{
case PS_THINKFRAME:
maxpage = thinkframe_hooks_length/PAGE_ENTRIES + 1;
break;
case PS_PRETHINKFRAME:
maxpage = prethinkframe_hooks_length/PAGE_ENTRIES + 1;
break;
case PS_POSTTHINKFRAME:
maxpage = postthinkframe_hooks_length/PAGE_ENTRIES + 1;
break;
default:
break;
}
if (cv_ps_thinkframe_page.value > maxpage)
CV_StealthSetValue(&cv_ps_thinkframe_page, maxpage);
@@ -1008,18 +996,18 @@ static void PS_DrawPostThinkFrameStats(void)
void M_DrawPerfStats(void)
{
if (cv_perfstats.value == 1) // rendering
if (cv_perfstats.value == PS_RENDER) // rendering
{
PS_UpdateFrameStats();
PS_DrawRenderStats();
}
else if (cv_perfstats.value == 2) // logic
else if (cv_perfstats.value == PS_LOGIC) // logic
{
// PS_UpdateTickStats is called in TryRunTics, since otherwise it would miss
// tics when frame skips happen
PS_DrawGameLogicStats();
}
else if (cv_perfstats.value >= 3) // lua thinkframe
else if (cv_perfstats.value >= PS_THINKFRAME) // lua thinkframe
{
if (!PS_IsLevelActive())
return;
@@ -1036,13 +1024,13 @@ void M_DrawPerfStats(void)
switch (cv_perfstats.value)
{
case 3:
case PS_THINKFRAME:
PS_DrawThinkFrameStats();
break;
case 4:
case PS_PRETHINKFRAME:
PS_DrawPreThinkFrameStats();
break;
case 5:
case PS_POSTTHINKFRAME:
PS_DrawPostThinkFrameStats();
break;
default:
+11
View File
@@ -26,6 +26,16 @@ typedef struct
void *history;
} ps_metric_t;
typedef enum
{
PS_OFF = 0,
PS_RENDER,
PS_LOGIC,
PS_THINKFRAME,
PS_PRETHINKFRAME,
PS_POSTTHINKFRAME
} ps_types_t;
typedef struct
{
ps_metric_t time_taken;
@@ -36,6 +46,7 @@ typedef struct
#define PS_STOP_TIMING(metric) metric.value.p = I_GetPreciseTime() - metric.value.p
extern ps_metric_t ps_tictime;
extern ps_metric_t ps_prevtictime;
extern ps_metric_t ps_playerthink_time;
extern ps_metric_t ps_thinkertime;
+1
View File
@@ -2632,6 +2632,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
if (i & 1)
P_SetObjectMomZ(mo, ns, true);
}
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->momz *= -1;
}
+3 -3
View File
@@ -245,12 +245,12 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
{
player_t *p = object->player; // will be NULL if not a player
player_t *player = object->player; // will be NULL if not a player
fixed_t zdist; // distance between bottoms
fixed_t speed = spring->info->mass; // conveniently, both fans and gas jets use this for the vertical thrust
SINT8 flipval = P_MobjFlip(spring); // virtually everything here centers around the thruster's gravity, not the object's!
if (p && object->state == &states[object->info->painstate]) // can't use fans and gas jets when player is in pain!
if (player && object->state == &states[object->info->painstate]) // can't use fans and gas jets when player is in pain!
return;
// is object's top below thruster's position? if not, calculate distance between their bottoms
@@ -276,7 +276,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
break;
if (flipval*object->momz >= FixedMul(speed, spring->scale)) // if object's already moving faster than your best, don't bother
break;
if (p && (p->climbing || p->pflags & PF_GLIDING)) // doesn't affect Knux when he's using his abilities!
if (player && (player->climbing || player->pflags & PF_GLIDING)) // doesn't affect Knux when he's using his abilities!
break;
object->momz += flipval*FixedMul(speed/4, spring->scale);
+1 -1
View File
@@ -466,7 +466,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// Check for collision with front side's midtexture if Effect 4 is set
if (linedef->flags & ML_EFFECT4
&& !linedef->polyobj) // don't do anything for polyobjects! ...for now
{
{
side_t *side = &sides[linedef->sidenum[0]];
fixed_t textop, texbottom, texheight;
fixed_t texmid, delta1, delta2;
+46 -35
View File
@@ -2573,7 +2573,7 @@ static void P_PlayerZMovement(mobj_t *mo)
P_SetPlayerMobjState(mo, S_KART_STND1);
}
#if 0 // praying that removing this dupe wont cause any issues...
#if 1 // praying that removing this dupe wont cause any issues...
if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope))
{
// Handle landing on slope during Z movement
@@ -9150,15 +9150,17 @@ void P_MobjThinker(mobj_t *mobj)
tmfloorthing = tmhitthing = NULL;
const sector_t *sec1 = mobj->subsector ? mobj->subsector->sector : NULL;
// 970 allows ANY mobj to trigger a linedef exec
if (!mobj->islocal && sec1 && GETSECSPECIAL(sec1->special, 2) == 8) // BEWARE: islocal does not exist in vanilla
// do NOT trigger linedef executors for "local" mobjs
if (!mobj->islocal)
{
sector_t *sec2;
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2);
// 970 allows ANY mobj to trigger a linedef exec
if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8)
{
sector_t *sec2;
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2);
}
}
if (mobj->scale != mobj->destscale)
@@ -9170,7 +9172,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT);
// Special thinker for scenery objects
if (mobj->flags & MF_SCENERY)
if (mobj->flags & MF_SCENERY && !mobj->player)
{
P_MobjSceneryThink(mobj);
return;
@@ -9262,7 +9264,8 @@ void P_MobjThinker(mobj_t *mobj)
mobj->eflags &= ~MFE_JUSTHITFLOOR;
}
if (mobj->type == MT_FALLINGROCK
// Sliding physics for slidey mobjs!
if ( mobj->type == MT_FALLINGROCK
|| mobj->type == MT_LITTLETUMBLEWEED
|| mobj->type == MT_BIGTUMBLEWEED
|| mobj->type == MT_FLINGRING
@@ -9307,21 +9310,24 @@ void P_MobjThinker(mobj_t *mobj)
if (P_MobjWasRemoved(mobj))
return;
if (P_WeaponOrPanel(mobj->type))
if ((mobj->health == 0) && // Fading tile
(mobj->type == MT_BOUNCEPICKUP
|| mobj->type == MT_RAILPICKUP
|| mobj->type == MT_AUTOPICKUP
|| mobj->type == MT_EXPLODEPICKUP
|| mobj->type == MT_SCATTERPICKUP
|| mobj->type == MT_GRENADEPICKUP))
{
if (mobj->health == 0) // Fading tile
{
INT32 value = mobj->info->damage/10;
value = mobj->fuse/value;
value = 10-value;
value--;
INT32 value = mobj->info->damage/10;
value = mobj->fuse/value;
value = 10-value;
value--;
if (value <= 0)
value = 1;
if (value <= 0)
value = 1;
mobj->frame &= ~FF_TRANSMASK;
mobj->frame |= value << FF_TRANSSHIFT;
}
mobj->frame &= ~FF_TRANSMASK;
mobj->frame |= value << FF_TRANSSHIFT;
}
}
@@ -9358,25 +9364,29 @@ void P_PushableThinker(mobj_t *mobj)
I_Assert(!P_MobjWasRemoved(mobj));
if (P_MobjWasRemovedCompat(mobj))
return;
sec = mobj->subsector->sector;
if (mobj->z == sec->floorheight && GETSECSPECIAL(sec->special, 2) == 1)
P_LinedefExecute(sec->tag, mobj, sec);
// do NOT trigger linedef executors for "local" mobjs
if (!mobj->islocal)
{
sector_t *sec2;
sec = mobj->subsector->sector;
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2);
if (mobj->z == sec->floorheight && GETSECSPECIAL(sec->special, 2) == 1)
P_LinedefExecute(sec->tag, mobj, sec);
{
sector_t *sec2;
sec2 = P_ThingOnSpecial3DFloor(mobj);
if (sec2 && GETSECSPECIAL(sec2->special, 2) == 1)
P_LinedefExecute(sec2->tag, mobj, sec2);
}
}
// it has to be pushable RIGHT NOW for this part to happen
if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy))
P_TryMove(mobj, mobj->x, mobj->y, true);
if (P_MobjWasRemovedCompat(mobj))
return;
if (mobj->fuse == 1) // it would explode in the MobjThinker code
{
mobj_t *spawnmo;
@@ -9402,7 +9412,8 @@ void P_PushableThinker(mobj_t *mobj)
}
spawnmo = P_SpawnMobj(x, y, z, mobj->type);
if (spawnmo)
if (!P_MobjWasRemovedCompat(spawnmo))
{
spawnmo->spawnpoint = mobj->spawnpoint;
P_UnsetThingPosition(spawnmo);
+1 -1
View File
@@ -113,7 +113,7 @@ typedef enum
// Don't use the blocklinks (inert but displayable)
MF_NOBLOCKMAP = 1<<4,
// Thin, paper-like collision bound (for visual equivalent, see FF_PAPERSPRITE)
MF_PAPERCOLLISION = 1<<5,
MF_PAPERCOLLISION = 1<<5,
// You can push this object. It can activate switches and things by pushing it on top.
MF_PUSHABLE = 1<<6,
// Object is a boss.
+10
View File
@@ -1108,7 +1108,11 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff2 = 0;
// not the default but the most probable
#ifdef COMPAT_VANILLA
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0)
#else
if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0 || mobj->pmomz !=0)
#endif
diff |= MD_MOM;
if (mobj->radius != mobj->info->radius)
diff |= MD_RADIUS;
@@ -1236,6 +1240,9 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
WRITEFIXED(save->p, mobj->momx);
WRITEFIXED(save->p, mobj->momy);
WRITEFIXED(save->p, mobj->momz);
#ifndef COMPAT_VANILLA
WRITEFIXED(save->p, mobj->pmomz);
#endif
}
if (diff & MD_RADIUS)
WRITEFIXED(save->p, mobj->radius);
@@ -2055,6 +2062,9 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
mobj->momx = READFIXED(save->p);
mobj->momy = READFIXED(save->p);
mobj->momz = READFIXED(save->p);
#ifndef COMPAT_VANILLA
mobj->pmomz = READFIXED(save->p);
#endif
} // otherwise they're zero, and the memset took care of it
if (diff & MD_RADIUS)
+97 -80
View File
@@ -180,7 +180,7 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg)
// don't use va() because the calling function probably uses it
char mapnum[10];
sprintf(mapnum, "%hd", gamemap);
snprintf(mapnum, sizeof(mapnum), "%hd", gamemap);
CON_LogMessage("Map ");
CON_LogMessage(mapnum);
CON_LogMessage(" is corrupt: ");
@@ -266,8 +266,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
mapheaderinfo[num]->actnum[0] = '\0';
mapheaderinfo[num]->typeoflevel = 0;
mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
mapheaderinfo[num]->musname[6] = 0;
snprintf(mapheaderinfo[num]->musname, sizeof(mapheaderinfo[num]->musname), "%sM", G_BuildMapName(i));
mapheaderinfo[num]->musname[sizeof(mapheaderinfo[num]->musname)-1] = 0;
mapheaderinfo[num]->mustrack = 0;
mapheaderinfo[num]->muspos = 0;
mapheaderinfo[num]->forcecharacter[0] = '\0';
@@ -318,15 +318,15 @@ void P_AllocMapHeader(INT16 i)
// Loads the vertexes for a level.
FUNCINLINE static ATTRINLINE void P_LoadVertices(UINT8 *data)
{
mapvertex_t *ml = (mapvertex_t *)data;
vertex_t *li = vertexes;
mapvertex_t *mv = (mapvertex_t *)data;
vertex_t *v = vertexes;
size_t i;
// Copy and convert vertex coordinates, internal representation as fixed.
for (i = 0; i < numvertexes; i++, li++, ml++)
for (i = 0; i < numvertexes; i++, v++, mv++)
{
li->x = SHORT(ml->x)<<FRACBITS;
li->y = SHORT(ml->y)<<FRACBITS;
v->x = SHORT(mv->x)<<FRACBITS;
v->y = SHORT(mv->y)<<FRACBITS;
}
}
@@ -479,65 +479,30 @@ static void P_SetupDirectionalLight(void)
static void P_LoadSegs(UINT8 *data)
{
INT32 rawlinedef, rawside;
mapseg_t *ml = (mapseg_t*)data;
seg_t *li = segs;
mapseg_t *ms = (mapseg_t*)data;
seg_t *seg = segs;
line_t *ldef;
size_t i;
// Set map lighting settings.
P_SetupDirectionalLight();
for (i = 0; i < numsegs; i++, li++, ml++)
for (i = 0; i < numsegs; i++, seg++, ms++)
{
INT16 v1, v2;
v1 = SHORT(ml->v1);
v2 = SHORT(ml->v2);
v1 = SHORT(ms->v1);
v2 = SHORT(ms->v2);
// e6y
// check and fix wrong references to non-existent vertexes
// see e1m9 @ NIVELES.WAD
// http://www.doomworld.com/idgames/index.php?id=12647
if ((unsigned)v1 >= numvertexes || (unsigned)v2 >= numvertexes)
{
if ((unsigned)v1 >= numvertexes)
CorruptMapWarning(va("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v1));
if ((unsigned)v2 >= numvertexes)
CorruptMapWarning(va("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v2));
// moved down for additional checks to avoid overflow
// if wrong vertexe's indexes are in SEGS lump
// see below for more detailed information
if (li->sidedef == &sides[li->linedef->sidenum[0]])
{
li->v1 = lines[ml->linedef].v1;
li->v2 = lines[ml->linedef].v2;
}
else
{
li->v1 = lines[ml->linedef].v2;
li->v2 = lines[ml->linedef].v1;
}
}
else
{
li->v1 = &vertexes[v1];
li->v2 = &vertexes[v2];
}
seg->angle = (SHORT(ms->angle)) << FRACBITS;
seg->offset = (SHORT(ms->offset)) << FRACBITS;
#ifdef HWRENDER
if (rendermode == render_opengl)
{
li->fv1.x = FixedToFloat(li->v1->x);
li->fv1.y = FixedToFloat(li->v1->y);
//li->fv1.z = FixedToFloat(li->v1->z); // z is unused in gl
li->fv2.x = FixedToFloat(li->v2->x);
li->fv2.y = FixedToFloat(li->v2->y);
//li->fv2.z = FixedToFloat(li->v2->z);
}
#endif
li->length = P_SegLength(li);
li->angle = (SHORT(ml->angle))<<FRACBITS;
li->offset = (SHORT(ml->offset))<<FRACBITS;
rawlinedef = SHORT(ml->linedef);
rawlinedef = SHORT(ms->linedef);
//e6y: check for wrong indexes
if ((unsigned)rawlinedef >= numlines)
@@ -546,8 +511,8 @@ static void P_LoadSegs(UINT8 *data)
}
ldef = &lines[rawlinedef];
li->linedef = ldef;
rawside = SHORT(ml->side);
seg->linedef = ldef;
rawside = SHORT(ms->side);
//e6y: fix wrong side index
if (rawside != 0 && rawside != 1)
@@ -562,9 +527,9 @@ static void P_LoadSegs(UINT8 *data)
I_Error("P_LoadSegs: linedef %d for seg %s references a non-existent sidedef %d", rawlinedef, sizeu1(i), ldef->sidenum[rawside]);
}
li->side = rawside;
seg->side = rawside;
li->sidedef = &sides[ldef->sidenum[rawside]];
seg->sidedef = &sides[ldef->sidenum[rawside]];
/* cph 2006/09/30 - our frontsector can be the second side of the
* linedef, so must check for NO_INDEX in case we are incorrectly
@@ -572,11 +537,11 @@ static void P_LoadSegs(UINT8 *data)
if (ldef->sidenum[rawside] == NO_INDEX)
{
CorruptMapWarning(va("P_LoadSegs: front of seg %s has no sidedef\n", sizeu1(i)));
li->frontsector = NULL;
seg->frontsector = NULL;
}
else
{
li->frontsector = sides[ldef->sidenum[rawside]].sector;
seg->frontsector = sides[ldef->sidenum[rawside]].sector;
}
if (ldef->flags & ML_TWOSIDED)
@@ -584,15 +549,58 @@ static void P_LoadSegs(UINT8 *data)
if (ldef->sidenum[rawside^1] == NO_INDEX)
{
CorruptMapWarning(va("P_LoadSegs: back of seg %s has no sidedef while being marked as double sided\n", sizeu1(i)));
li->backsector = NULL;
seg->backsector = NULL;
}
else
{
li->backsector = sides[ldef->sidenum[rawside^1]].sector;
seg->backsector = sides[ldef->sidenum[rawside^1]].sector;
}
}
P_UpdateSegLightOffset(li);
// e6y
// check and fix wrong references to non-existent vertexes
// see e1m9 @ NIVELES.WAD
// http://www.doomworld.com/idgames/index.php?id=12647
if ((unsigned)v1 >= numvertexes || (unsigned)v2 >= numvertexes)
{
if ((unsigned)v1 >= numvertexes)
CorruptMapWarning(va("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v1));
if ((unsigned)v2 >= numvertexes)
CorruptMapWarning(va("P_LoadSegs: seg %s references a non-existent vertex %d\n", sizeu1(i), v2));
if (seg->sidedef == &sides[seg->linedef->sidenum[0]])
{
seg->v1 = lines[ms->linedef].v1;
seg->v2 = lines[ms->linedef].v2;
}
else
{
seg->v1 = lines[ms->linedef].v2;
seg->v2 = lines[ms->linedef].v1;
}
}
else
{
seg->v1 = &vertexes[v1];
seg->v2 = &vertexes[v2];
}
#ifdef HWRENDER
if (rendermode == render_opengl)
{
seg->fv1.x = FixedToFloat(seg->v1->x);
seg->fv1.y = FixedToFloat(seg->v1->y);
//seg->fv1.z = FixedToFloat(seg->v1->z); // z is unused in gl
seg->fv2.x = FixedToFloat(seg->v2->x);
seg->fv2.y = FixedToFloat(seg->v2->y);
//seg->fv2.z = FixedToFloat(seg->v2->z);
}
#endif
seg->length = P_SegLength(seg);
P_UpdateSegLightOffset(seg);
}
}
@@ -610,10 +618,6 @@ FUNCINLINE static ATTRINLINE void P_LoadSubsectors(void *data)
}
}
//
// P_LoadSectors
//
//
// levelflats
//
@@ -665,13 +669,17 @@ static void P_CheckCyanFlat(levelflat_t *levelflat)
const char *flatname = W_CheckNameForNum(levelflat->lumpnum);
// hack for gba rainbow roads cyan floors
if (UNLIKELY(memcmp(flatname, "GBA_RRF5", 8) == 0 && flatname[8] == 0))
if (UNLIKELY(flatname && memcmp(flatname, "GBA_RRF5", 8) == 0 && flatname[8] == 0))
{
levelflat->cyan = false;
return;
}
const UINT8 *flat = R_GetFlat(levelflat->lumpnum);
if (!flat)
return;
const size_t size = W_LumpLength(levelflat->lumpnum);
for (size_t steppy = 0; steppy < size; steppy++)
@@ -791,6 +799,10 @@ INT32 P_CheckLevelFlat(const char *flatname)
return (INT32)i;
}
//
// P_LoadSectors
//
static const sector_t sector_default = {
.nexttag = -1,
.firsttag = -1,
@@ -1894,7 +1906,7 @@ static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count)
// because making both the WAD and PK3 loading code use
// the same functions is trickier than it looks for blockmap
// -- Monster Iestyn 09/01/18
static boolean P_LoadRawBlockMap(UINT8 *data, size_t count)
static boolean P_LoadBlockMap(UINT8 *data, size_t count)
{
if (!count || count >= 0x20000)
return false;
@@ -2120,7 +2132,7 @@ static void P_LoadMapLUT(const virtres_t* virt)
rejectmatrix = NULL;
}
if (!(virtblockmap && P_LoadRawBlockMap(virtblockmap->data, virtblockmap->size)))
if (!(virtblockmap && P_LoadBlockMap(virtblockmap->data, virtblockmap->size)))
P_CreateBlockMap();
}
@@ -2193,7 +2205,7 @@ void P_SetupLevelSky(INT32 skynum, boolean global)
{
char skytexname[12];
sprintf(skytexname, "SKY%d", skynum);
snprintf(skytexname, sizeof(skytexname), "SKY%d", skynum);
skytexture = R_TextureNumForName(skytexname);
levelskynum = skynum;
@@ -2413,7 +2425,8 @@ static void P_RunLevelScript(const char *scriptname)
lumpnum_t lumpnum;
char newname[9];
strlcpy(newname, scriptname, sizeof(newname));
strncpy(newname, scriptname, sizeof(newname)-1);
newname[sizeof(newname)-1] = '\0';
lumpnum = W_CheckNumForName(newname);
@@ -2423,7 +2436,7 @@ static void P_RunLevelScript(const char *scriptname)
return;
}
COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE));
COM_BufInsertTextEx(W_CacheLumpNum(lumpnum, PU_CACHE), W_LumpLength(lumpnum));
}
else
{
@@ -2438,23 +2451,26 @@ static void P_ForceCharacter(const char *forcecharskin)
if (netgame)
{
char skincmd[33];
if (splitscreen)
{
sprintf(skincmd, "skin2 %s\n", forcecharskin);
snprintf(skincmd, sizeof(skincmd), "skin2 %s\n", forcecharskin);
CV_Set(&cv_skin2, forcecharskin);
if (splitscreen > 1)
{
sprintf(skincmd, "skin3 %s\n", forcecharskin);
snprintf(skincmd, sizeof(skincmd), "skin3 %s\n", forcecharskin);
CV_Set(&cv_skin3, forcecharskin);
if (splitscreen > 2)
{
sprintf(skincmd, "skin4 %s\n", forcecharskin);
snprintf(skincmd, sizeof(skincmd), "skin4 %s\n", forcecharskin);
CV_Set(&cv_skin4, forcecharskin);
}
}
}
sprintf(skincmd, "skin %s\n", forcecharskin);
snprintf(skincmd, sizeof(skincmd), "skin %s\n", forcecharskin);
COM_BufAddText(skincmd);
}
else
@@ -2511,7 +2527,7 @@ static void P_LoadRecordGhosts(void)
const char *mapname = G_BuildMapName(gamemap);
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, mapname);
snprintf(gpath, glen, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, mapname);
// Best Time ghost
if (cv_ghost_besttime.value)
@@ -2867,7 +2883,8 @@ static void P_SetupPlayer(void)
if (!demo.playback && multiplayer && D_NumPlayers())
{
static char buf[256];
sprintf(buf, "replay"PATHSEP"online"PATHSEP"%d-%s", (int)(time(NULL)), G_BuildMapName(gamemap));
snprintf(buf, sizeof(buf), "replay"PATHSEP"online"PATHSEP"%d-%s", (int)(time(NULL)), G_BuildMapName(gamemap));
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"online", srb2home), 0755);
@@ -3049,7 +3066,7 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate)
// Don't include these in the fade!
char tx[64];
V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
snprintf(tx, 63, "%s%s%s",
snprintf(tx, sizeof(tx)-1, "%s%s%s",
mapheader->lvlttl,
(strlen(mapheader->zonttl) > 0) ? va(" %s",mapheader->zonttl) : // SRB2kart
((mapheader->levelflags & LF_NOZONE) ? "" : " Zone"),
+5 -12
View File
@@ -2161,7 +2161,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
newname[1] = 'C';
newname[2] = 'R';
scrnum = sides[line->sidenum[0]].textureoffset>>FRACBITS;
scrnum = sides[line->sidenum[0]].textureoffset >> FRACBITS;
if (scrnum < 0 || scrnum > 999)
{
scrnum = 0;
@@ -2169,9 +2169,9 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
}
else
{
newname[5] = (char)('0' + (char)((scrnum/100)));
newname[6] = (char)('0' + (char)((scrnum%100)/10));
newname[7] = (char)('0' + (char)(scrnum%10));
newname[5] = (char)('0' + (char)((scrnum / 100)));
newname[6] = (char)('0' + (char)((scrnum % 100) / 10));
newname[7] = (char)('0' + (char)(scrnum % 10));
}
newname[8] = '\0';
@@ -2184,14 +2184,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
else
{
// W_CacheLumpNum may not have null terminator, so we need to do this :blobcatgooglyholditsheadinitshands:
size_t len = W_LumpLength(lumpnum);
char *script = Z_Malloc(len+1, PU_STATIC, NULL);
memcpy(script, W_CacheLumpNum(lumpnum, PU_CACHE), len);
script[len] = 0;
COM_BufInsertText(script);
Z_Free(script);
COM_BufInsertTextEx(W_CacheLumpNum(lumpnum, PU_CACHE), W_LumpLength(lumpnum));
}
}
break;
+7 -1
View File
@@ -38,6 +38,8 @@
#include "i_video.h" // rendermode
#include "m_perfstats.h"
#include "lua_profile.h"
// Object place
#include "m_cheat.h"
@@ -622,6 +624,8 @@ void P_Ticker(boolean run)
}
}
LUA_ResetTicTimers();
ps_lua_mobjhooks.value.i = 0;
ps_checkposition_calls.value.i = 0;
@@ -629,6 +633,7 @@ void P_Ticker(boolean run)
LUA_HookPreThinkFrame();
PS_STOP_TIMING(ps_lua_prethinkframe_time);
// OK! Now that we got all of that sorted, players can think!
PS_START_TIMING(ps_playerthink_time);
for (i = 0; i < MAXPLAYERS; i++)
{
@@ -675,6 +680,7 @@ void P_Ticker(boolean run)
PS_STOP_TIMING(ps_lua_thinkframe_time);
}
// Run shield positioning
P_RunOverlays();
P_RunShadows();
@@ -796,7 +802,7 @@ void P_Ticker(boolean run)
if (!player->mo)
continue;
const boolean skybox = (skyboxmo[0] && cv_skybox.value);
const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on
if (skyVisiblePerPlayer[i] && skybox)
{
+12 -4
View File
@@ -625,15 +625,23 @@ boolean P_EndingMusic(player_t *player)
}
if (G_RaceGametype() && bestlocalpos == MAXPLAYERS+1)
sprintf(buffer, "k*fail"); // F-Zero death results theme
{
snprintf(buffer, sizeof(buffer), "k*fail"); // F-Zero death results theme
}
else
{
if (bestlocalpos == 1)
sprintf(buffer, "k*win");
{
snprintf(buffer, sizeof(buffer), "k*win");
}
else if (isPlayerLosing(bestlocalplayer))
sprintf(buffer, "k*lose");
{
snprintf(buffer, sizeof(buffer), "k*lose");
}
else
sprintf(buffer, "k*ok");
{
snprintf(buffer, sizeof(buffer), "k*ok");
}
}
S_SpeedMusic(1.0f);
+1 -1
View File
@@ -395,7 +395,7 @@ static void R_AddLine(seg_t *line)
// Find the other side!
INT32 line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->linedef->tag, -1);
if (line->linedef == &lines[line2])
if (line2 >= 0 && line->linedef == &lines[line2])
line2 = P_FindSpecialLineFromTag(PORTALSPECIAL, line->linedef->tag, line2);
if (line2 >= 0) // found it!
+4 -8
View File
@@ -340,18 +340,14 @@ void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out)
return;
}
const boolean doreset = mobj->resetinterp && (mobj->type != MT_GHOST) && (mobj->type != MT_PLAYERRETICULE) && (mobj->type != MT_SHADOW);
out->x = doreset ? mobj->x : R_LerpFixed(mobj->old_x, mobj->x, frac);
out->y = doreset ? mobj->y : R_LerpFixed(mobj->old_y, mobj->y, frac);
out->z = doreset ? mobj->z : R_LerpFixed(mobj->old_z, mobj->z, frac);
out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac);
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
out->spritexscale = mobj->resetinterp ? mobj->spritexscale : R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac);
out->spriteyscale = mobj->resetinterp ? mobj->spriteyscale : R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac);
out->spritexoffset = mobj->resetinterp ? mobj->spritexoffset : R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac);
out->spriteyoffset = mobj->resetinterp ? mobj->spriteyoffset : R_LerpFixed(mobj->old_spriteyoffset, mobj->spriteyoffset, frac);
out->scale = mobj->resetinterp ? mobj->scale : R_LerpFixed(mobj->old_scale, mobj->scale, frac);
//out->subsector = R_PointInSubsector(out->x, out->y); // this is unused
if (mobj->player)
+1 -1
View File
@@ -1882,7 +1882,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
// big room fix
if (longboi)
rw_distance = (fixed_t)R_CalcSegDist(curline,viewx,viewy);
rw_distance = (fixed_t)R_CalcSegDist(curline, viewx, viewy);
ds_p->x1 = rw_x = start;
ds_p->x2 = stop;
+11 -11
View File
@@ -334,7 +334,7 @@ lumpnum_t S_GetSfxLumpNum(sfxinfo_t *sfx)
char namebuf[9];
lumpnum_t sfxlump;
sprintf(namebuf, "ds%s", sfx->name);
snprintf(namebuf, sizeof(namebuf), "ds%s", sfx->name);
sfxlump = W_CheckNumForName(namebuf);
if (sfxlump != LUMPERROR)
@@ -433,7 +433,7 @@ static boolean S_CheckSameSoundLimit(sfxenum_t sfx_id)
return true;
for (cnum = 0; cnum < numofchannels; cnum++)
if ((size_t)(channels[cnum].sfxinfo - S_sfx) == (size_t)sfx_id)
if (channels[cnum].sfxinfo == &S_sfx[sfx_id])
scount++;
//CONS_Printf("same sound count: %d for sfx: %d\n", scount, sfx_id);
@@ -864,18 +864,18 @@ void S_SetSfxVolume(INT32 volume)
if (volume < 0 || volume > 31)
CONS_Alert(CONS_WARNING, "sfxvolume should be between 0-31\n");
CV_SetValue(&cv_soundvolume, volume&0x1F);
CV_SetValue(&cv_soundvolume, volume & 0x1F);
actualsfxvolume = cv_soundvolume.value; // check for change of var
// now hardware volume
I_SetSfxVolume(volume&0x1F);
I_SetSfxVolume(volume & 0x1F);
}
void S_ClearSfx(void)
{
size_t i;
for (i = 1; i < NUMSFX; i++)
I_FreeSfx(S_sfx + i);
I_FreeSfx(&S_sfx[i]);
}
static void S_StopChannel(INT32 cnum)
@@ -1067,12 +1067,12 @@ INT32 S_OriginPlaying(void *origin)
// Searches through the channels and checks if a given id
// is playing anywhere.
INT32 S_IdPlaying(sfxenum_t id)
INT32 S_IdPlaying(sfxenum_t sfx_id)
{
INT32 cnum;
for (cnum = 0; cnum < numofchannels; cnum++)
if ((size_t)(channels[cnum].sfxinfo - S_sfx) == (size_t)id)
if (channels[cnum].sfxinfo == &S_sfx[sfx_id])
return 1;
return 0;
@@ -1080,7 +1080,7 @@ INT32 S_IdPlaying(sfxenum_t id)
// Searches through the channels and checks for
// origin x playing sound id y.
INT32 S_SoundPlaying(void *origin, sfxenum_t id)
INT32 S_SoundPlaying(void *origin, sfxenum_t sfx_id)
{
INT32 cnum;
@@ -1089,8 +1089,8 @@ INT32 S_SoundPlaying(void *origin, sfxenum_t id)
for (cnum = 0; cnum < numofchannels; cnum++)
{
if (channels[cnum].origin == origin
&& (size_t)(channels[cnum].sfxinfo - S_sfx) == (size_t)id)
if (channels[cnum].origin == origin &&
channels[cnum].sfxinfo == &S_sfx[sfx_id])
return 1;
}
@@ -2193,7 +2193,7 @@ static void Command_Tunes_f(void)
track = (UINT16)atoi(COM_Argv(2))-1;
if (tunenum)
snprintf(mapmusic.name, 7, "%sM", G_BuildMapName(tunenum));
snprintf(mapmusic.name, sizeof(mapmusic.name), "%sM", G_BuildMapName(tunenum));
else
strlcpy(mapmusic.name, tunearg, sizeof(mapmusic.name));
+2 -2
View File
@@ -286,8 +286,8 @@ void S_SetSfxVolume(INT32 volume);
void S_SetMusicVolume(INT32 volume);
INT32 S_OriginPlaying(void *origin);
INT32 S_IdPlaying(sfxenum_t id);
INT32 S_SoundPlaying(void *origin, sfxenum_t id);
INT32 S_IdPlaying(sfxenum_t sfx_id);
INT32 S_SoundPlaying(void *origin, sfxenum_t sfx_id);
void S_StartSoundName(void *mo, const char *soundname);
+8
View File
@@ -177,6 +177,10 @@ if(${SDL2_FOUND})
)
endif()
if("${CMAKE_SYSTEM_NAME}" MATCHES "OpenBSD")
target_link_libraries(SRB2SDL2 PRIVATE pthread execinfo)
endif()
if(${CMAKE_SYSTEM} MATCHES Windows AND ${CMAKE_C_COMPILER_ID} MATCHES "GNU" AND ${SRB2_SYSTEM_BITS} EQUAL 32)
target_link_libraries(SRB2SDL2 PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/../../libs/drmingw/lib/win32/libexchndl.a"
@@ -243,6 +247,10 @@ if(${SDL2_FOUND})
target_link_options(SRB2SDL2 PRIVATE -fsanitize=undefined)
endif()
if(NOT SRB2_CONFIG_MUMBLE)
target_compile_options(SRB2SDL2 PRIVATE -DNOMUMBLE)
endif()
## strip debug symbols into separate file when using gcc
# if(CMAKE_COMPILER_IS_GNUCC)
# if(${CMAKE_BUILD_TYPE} MATCHES Debug)
+71 -35
View File
@@ -57,10 +57,13 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#include <time.h>
#include <stdlib.h>
#include <string.h>
#ifdef __GNUC__
#include <unistd.h>
#endif
#if defined (__unix__) || defined (UNIXCOMMON)
#include <sys/stat.h>
#include <fcntl.h>
#endif
@@ -577,7 +580,7 @@ void I_OutputMsg(const char *fmt, ...)
I_Error("I_OutputMsg: Out of memory!\n");
va_start(argptr, fmt);
vsprintf(txt, fmt, argptr);
vsnprintf(txt, len+1, fmt, argptr);
va_end(argptr);
#ifdef HAVE_TTF
@@ -585,7 +588,7 @@ void I_OutputMsg(const char *fmt, ...)
DEFAULTFONTBGR, DEFAULTFONTBGG, DEFAULTFONTBGB, DEFAULTFONTBGA, txt);
#endif
len = strlen(txt);
len = strnlen(txt, len+1);
#ifdef LOGMESSAGES
if (logstream)
@@ -983,13 +986,13 @@ void I_InitJoystick(UINT8 index)
{
char dbpath[1024];
sprintf(dbpath, "%s" PATHSEP "gamecontrollerdb.txt", srb2path);
snprintf(dbpath, sizeof(dbpath), "%s" PATHSEP "gamecontrollerdb.txt", srb2path);
SDL_GameControllerAddMappingsFromFile(dbpath);
}
{
char dbpath[1024];
sprintf(dbpath, "%s" PATHSEP "gamecontrollerdb_user.txt", srb2home);
snprintf(dbpath, sizeof(dbpath), "%s" PATHSEP "gamecontrollerdb_user.txt", srb2home);
SDL_GameControllerAddMappingsFromFile(dbpath);
}
@@ -1151,8 +1154,7 @@ const char *I_GetJoyName(INT32 joyindex)
if (tempname)
{
memcpy(joyname, tempname, 255);
joyname[255] = '\0';
snprintf(joyname, sizeof(joyname), "%s", tempname);
}
}
@@ -1279,7 +1281,7 @@ static void I_SetupMumble(void)
int shmfd;
char memname[256];
snprintf(memname, 256, "/MumbleLink.%d", getuid());
snprintf(memname, sizeof(memname), "/MumbleLink.%d", getuid());
shmfd = shm_open(memname, O_RDWR, S_IRUSR | S_IWUSR);
if (shmfd < 0)
@@ -1396,19 +1398,31 @@ void I_Sleep(UINT32 ms)
void I_SleepDuration(precise_t duration)
{
#if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) || defined(__OpenBSD__)
UINT64 precision = I_GetPrecisePrecision();
precise_t dest = I_GetPreciseTime() + duration;
#ifdef __OpenBSD__
precise_t slack = (precision / 50); // 20 ms slack
#else
precise_t slack = (precision / 5000); // 0.2 ms slack
#endif
if (duration > slack)
{
duration -= slack;
struct timespec ts = {
.tv_sec = static_cast<__time_t>(duration / precision),
#ifdef __BIONIC__
.tv_nsec = static_cast<long>(duration * 1000000000 / precision % 1000000000),
#else
.tv_nsec = static_cast<__syscall_slong_t>(duration * 1000000000 / precision % 1000000000),
#endif
};
int status;
#ifdef __OpenBSD__
do status = nanosleep(&ts, &ts);
#else
do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
#endif
while (status == EINTR);
}
@@ -1693,16 +1707,20 @@ static void I_PrintSignal(INT32 signal_num, boolean core_dumped, char *signal_ms
if (core_dumped)
{
if (sigmsg)
sprintf(signal_msg, "%s (core dumped)", sigmsg);
{
snprintf(signal_msg, 512, "%s (core dumped)", sigmsg);
}
else
{
strcat(signal_msg, " (core dumped)");
}
}
else
{
sprintf(signal_msg, "%s", sigmsg);
snprintf(signal_msg, 512, "%s", sigmsg);
}
sprintf(signal_name, "%s", signame);
snprintf(signal_name, 128, "%s", signame);
}
int I_OpenURL(const char *url)
@@ -1880,7 +1898,7 @@ FUNCNORETURN static ATTRNORETURN void newsignalhandler_Warn(const char *pr)
{
char text[128];
snprintf(text, sizeof text,
snprintf(text, sizeof(text),
"Error while setting up signal reporting: %s: %s",
pr,
strerror(errno)
@@ -2096,7 +2114,7 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...)
if (errorcount > 20)
{
va_start(argptr, error);
vsnprintf(buffer, 8192, error, argptr);
vsnprintf(buffer, sizeof(buffer), error, argptr);
va_end(argptr);
sigttl = "SRB2Kart " VERSIONSTRING " Recursive Error";
@@ -2110,7 +2128,7 @@ FUNCIERROR void ATTRNORETURN I_Error(const char *error, ...)
// Display error message in the console before we start shutting it down
va_start(argptr, error);
vsnprintf(buffer, 8192, error, argptr);
vsnprintf(buffer, sizeof(buffer), error, argptr);
va_end(argptr);
I_OutputMsg("\nI_Error(): %s\n", buffer);
@@ -2253,6 +2271,7 @@ void I_ShutdownSystem(void)
for (c = MAX_QUIT_FUNCS-1; c >= 0; c--)
if (quit_funcs[c])
(*quit_funcs[c])();
#ifdef LOGMESSAGES
if (logstream)
{
@@ -2337,7 +2356,8 @@ char *I_GetUserName(void)
}
}
}
strncpy(username, p, MAXPLAYERNAME);
snprintf(username, sizeof(username), "%s", p);
}
if (!fastcmp(username, ""))
@@ -2361,6 +2381,24 @@ INT32 I_mkdir(const char *dirname, INT32 unixright)
#endif
}
INT32 I_ChDir(const char *path)
{
#ifdef _WIN32
return (SetCurrentDirectoryA(path) ? 0 : -1);
#else
return chdir(path);
#endif
}
char *I_GetCwd(char *buf, size_t size)
{
#ifdef _WIN32
return (GetCurrentDirectoryA((DWORD)size, buf) ? buf : NULL);
#else
return getcwd(buf, size);
#endif
}
char *I_GetEnv(const char *name)
{
#ifdef NEED_SDL_GETENV
@@ -2382,13 +2420,15 @@ INT32 I_PutEnv(char *variable)
INT32 I_ClipboardCopy(const char *data, size_t size)
{
char storage[256];
if (size > 255)
size = 255;
memcpy(storage, data, size);
storage[size] = 0;
snprintf(storage, sizeof(storage), "%.*s", (int)size, data);
if (SDL_SetClipboardText(storage))
return 0;
return -1;
}
@@ -2401,7 +2441,7 @@ const char *I_ClipboardPaste(void)
return NULL;
clipboard_contents = SDL_GetClipboardText();
strlcpy(clipboard_modified, clipboard_contents, 256);
snprintf(clipboard_modified, sizeof(clipboard_modified), "%s", clipboard_contents);
SDL_free(clipboard_contents);
while (*i)
@@ -2417,6 +2457,7 @@ const char *I_ClipboardPaste(void)
*i = '?'; // Nonprintable chars become question marks
++i;
}
return (const char *)&clipboard_modified;
}
@@ -2430,28 +2471,23 @@ const char *I_ClipboardPaste(void)
*/
static boolean isWadPathOk(const char *path)
{
char *wad3path = static_cast<char*>(malloc(256));
char wad3path[256];
if (!wad3path)
return false;
sprintf(wad3path, pandf, path, WADKEYWORD);
snprintf(wad3path, sizeof(wad3path), pandf, path, WADKEYWORD);
if (FIL_ReadFileOK(wad3path))
{
free(wad3path);
return true;
}
free(wad3path);
return false;
}
static void pathonly(char *s)
static void pathonly(char *s, size_t size)
{
size_t j;
for (j = strlen(s); j != (size_t)-1; j--)
for (j = strnlen(s, size); j != (size_t)-1; j--)
{
if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/'))
{
@@ -2478,11 +2514,12 @@ static const char *searchWad(const char *searchDir)
static char tempsw[256] = "";
filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD);
snprintf(tempsw, sizeof(tempsw), "%s", WADKEYWORD);
fstemp = filesearch(tempsw, searchDir, NULL, true, 20);
if (fstemp == FS_FOUND)
{
pathonly(tempsw);
pathonly(tempsw, sizeof(tempsw));
return tempsw;
}
@@ -2520,7 +2557,7 @@ static const char *locateWad(void)
#ifndef NOCWD
// examine current dir
strcpy(returnWadPath, ".");
snprintf(returnWadPath, sizeof(returnWadPath), "%s", ".");
I_OutputMsg(",%s", returnWadPath);
if (isWadPathOk(returnWadPath))
return NULL;
@@ -2532,7 +2569,7 @@ static const char *locateWad(void)
// examine user jart directory
if ((envstr = I_GetEnv("HOME")) != NULL)
{
sprintf(returnWadPath, "%s" PATHSEP DEFAULTDIR, envstr);
snprintf(returnWadPath, sizeof(returnWadPath), "%s" PATHSEP DEFAULTDIR, envstr);
CHECKWADPATH(returnWadPath);
}
#endif
@@ -2546,7 +2583,7 @@ static const char *locateWad(void)
// examine default dirs
for (i = 0; wadDefaultPaths[i]; i++)
{
strcpy(returnWadPath, wadDefaultPaths[i]);
snprintf(returnWadPath, sizeof(returnWadPath), "%s", wadDefaultPaths[i]);
CHECKWADPATH(returnWadPath);
}
@@ -2574,12 +2611,11 @@ extern "C" const char *I_LocateWad(void)
// change to the directory where we found srb2.srb
#if defined (_WIN32)
waddir = _fullpath(NULL, waddir, MAX_PATH);
SetCurrentDirectoryA(waddir);
#else
waddir = realpath(waddir, NULL);
if (waddir == NULL || chdir(waddir) == -1)
I_OutputMsg("Couldn't change working directory\n");
#endif
if (waddir == NULL || I_ChDir(waddir) == -1)
I_OutputMsg("Couldn't change working directory\n");
}
return waddir;
+8 -2
View File
@@ -183,13 +183,17 @@ void I_TTFDrawText(TTF_Font *font, TextQuality quality, INT32 fgR, INT32 fgG, IN
TTFRect.x = TTFRectCheck.x;
TTFRect.y = TTFRectCheck.y;
}
// Copy the character to the text buffer.
sprintf(textbuffer, "%s%c", textbuffer, c);
snprintf(textbuffer, sizeof(textbuffer), "%s%c", textbuffer, c);
// Hack to allow TTF_SizeText to work properly.
sprintf(linebuffer, "%c", c);
snprintf(linebuffer, sizeof(linebuffer), "%c", c);
// If we have reached the end of the screen, move to the next available line.
TTF_SizeText(currentfont, linebuffer, &w, &h);
TTFRectCheck.x += w;
if (TTFRectCheck.x >= res.width)
{
// Render cached text to the SDL surface.
@@ -204,8 +208,10 @@ void I_TTFDrawText(TTF_Font *font, TextQuality quality, INT32 fgR, INT32 fgG, IN
TTFRect.y = TTFRectCheck.y;
}
}
// Add 1 to the pointer reference for the character to process.
textmsg++;
// Copy contents of the now-old buffer to somewhere else, so it can be referenced in next loop.
prevc = c;
}
+3 -3
View File
@@ -1538,9 +1538,9 @@ const char *VID_GetModeName(INT32 modeNum)
if (modeNum > MAXWINMODES)
return NULL;
sprintf(&vidModeName[modeNum][0], "%dx%d",
windowedModes[modeNum][0],
windowedModes[modeNum][1]);
snprintf(&vidModeName[modeNum][0], sizeof(vidModeName[modeNum]), "%dx%d",
windowedModes[modeNum][0],
windowedModes[modeNum][1]);
return &vidModeName[modeNum][0];
}
+1 -1
View File
@@ -868,7 +868,7 @@ boolean I_SetSongSpeed(float speed)
{
// deprecated in 0.5.0
char modspd[13];
sprintf(modspd, "%g", speed);
snprintf(modspd, sizeof(modspd), "%g", speed);
openmpt_module_ctl_set(openmpt_mhandle, "play.tempo_factor", modspd);
}
#else
+1 -1
View File
@@ -591,7 +591,7 @@ static void ST_overlayDrawer(void)
char name[MAXPLAYERNAME+12];
INT32 y = (stplyrnum == 0) ? 4 : BASEVIDHEIGHT/2-12;
sprintf(name, "VIEWPOINT: %s", player_names[stplyr-players]);
snprintf(name, sizeof(name), "VIEWPOINT: %s", player_names[stplyr-players]);
V_DrawRightAlignedThinString(BASEVIDWIDTH-40, y, V_HUDTRANSHALF|V_ALLOWLOWERCASE|K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOBOTTOM|V_SNAPTORIGHT), name);
}
else if (splitscreen)
+14 -7
View File
@@ -581,13 +581,19 @@ const char *GetPalette(void)
if (user && user[0])
{
if (W_CheckNumForName(user) == LUMPERROR)
const lumpnum_t palnum = W_CheckNumForName(user);
if (palnum == LUMPERROR)
{
CONS_Alert(CONS_WARNING, "cv_palette %s lump does not exist\n", user);
}
else if (W_LumpLength(palnum) % (256 * 3) != 0) // not divisable by 768, so most def not a valid palette, idk if theres a better way to check this
{
CONS_Alert(CONS_WARNING, "cv_palette %s is not a valid palette lump\n", user);
}
else
{
return cv_palette.string;
return user;
}
}
@@ -609,15 +615,16 @@ void V_ReloadPalette(void)
void V_SetPalette(INT32 palettenum)
{
RGBA_t *pal = NULL;
if (!pLocalPalette)
V_ReloadPalette();
#ifdef HWRENDER
if (rendermode == render_soft ||
(rendermode == render_opengl && HWR_ShouldUsePaletteRendering())) // opengl without paletterendering hates subpalettes
#endif
if (palettenum == 0)
{
if (palettenum == 0)
#ifdef HWRENDER
if (rendermode == render_soft ||
(rendermode == render_opengl && HWR_ShouldUsePaletteRendering())) // opengl without paletterendering hates subpalettes
#endif
{
palettenum = cv_palettenum.value;
}
+2 -4
View File
@@ -292,8 +292,7 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum)
if (!name)
I_Error("W_LoadDehackedLumpsPK3: Out of memory!\n");
sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname);
name[length] = '\0';
snprintf(name, length + 1, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname);
CONS_Printf("Loading SOC from %s\n", name);
DEH_LoadDehackedLumpPwad(wadnum, posStart);
free(name);
@@ -328,8 +327,7 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum)
if (!name)
I_Error("W_LoadDehackedLumps: Out of memory!\n");
sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname);
name[length] = '\0';
snprintf(name, length + 1, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname);
CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
DEH_LoadDehackedLumpPwad(wadnum, lump);
+1 -1
View File
@@ -118,7 +118,7 @@ static VOID FPrintf(HANDLE fileHandle, LPCSTR lpFmt, ...)
DWORD bytesWritten;
va_start(arglist, lpFmt);
vsnprintf(str, 1999, lpFmt, arglist);
vsnprintf(str, sizeof(str), lpFmt, arglist);
va_end(arglist);
WriteFile(fileHandle, str, (DWORD)strlen(str), &bytesWritten, NULL);
+37 -21
View File
@@ -153,7 +153,7 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
;
else if ((data.rankingsmode = (boolean)rankingsmode))
{
sprintf(data.levelstring, "* Total Rankings *");
snprintf(data.levelstring, sizeof(data.levelstring), "* Total Rankings *");
data.encore = false;
}
else
@@ -162,32 +162,41 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
if (mapheaderinfo[prevmap]->levelflags & LF_NOZONE)
{
if (mapheaderinfo[prevmap]->actnum[0])
{
snprintf(data.levelstring,
sizeof data.levelstring,
sizeof(data.levelstring),
"* %s %s *",
mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->actnum);
}
else
{
snprintf(data.levelstring,
sizeof data.levelstring,
sizeof(data.levelstring),
"* %s *",
mapheaderinfo[prevmap]->lvlttl);
}
}
else
{
const char *zonttl = (mapheaderinfo[prevmap]->zonttl[0] ? mapheaderinfo[prevmap]->zonttl : "Zone");
if (mapheaderinfo[prevmap]->actnum[0])
{
snprintf(data.levelstring,
sizeof data.levelstring,
sizeof(data.levelstring),
"* %s %s %s *",
mapheaderinfo[prevmap]->lvlttl, zonttl, mapheaderinfo[prevmap]->actnum);
}
else
{
snprintf(data.levelstring,
sizeof data.levelstring,
sizeof(data.levelstring),
"* %s %s *",
mapheaderinfo[prevmap]->lvlttl, zonttl);
}
}
data.levelstring[sizeof data.levelstring - 1] = '\0';
data.levelstring[sizeof(data.levelstring) - 1] = '\0';
data.encore = encoremode;
@@ -265,13 +274,13 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
//
static void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 x, INT32 hilicol)
{
INT32 i;
if (standings->numplayers == 0)
{
return;
}
INT32 i;
#define NUMFORNEWCOLUMN 8
INT32 y = 41, gutter = ((standings->numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2));
INT32 dupadjust = cv_betainterscreen.value ? 314 : vid.scaledwidth, duptweak = cv_betainterscreen.value ? -3 : (dupadjust - BASEVIDWIDTH)/2;
@@ -312,6 +321,12 @@ static void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 x, INT32 hilicol)
const UINT8 pnum = standings->num[i];
player_t *player = &players[pnum];
#if MAXPLAYERS > 16
// 32 Player TODO: port over and cleanup standings drawer from sat-32p/blankart
if (i > 16)
break;
#endif
if (pnum == MAXPLAYERS)
;
else if (!playeringame[pnum] || player->spectator)
@@ -360,9 +375,9 @@ static void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 x, INT32 hilicol)
if (standings->increase[pnum] != UINT8_MAX)
{
if (standings->increase[pnum] > 9)
snprintf(strtime, sizeof strtime, "(+%02d)", standings->increase[pnum]);
snprintf(strtime, sizeof(strtime), "(+%02d)", standings->increase[pnum]);
else
snprintf(strtime, sizeof strtime, "(+ %d)", standings->increase[pnum]);
snprintf(strtime, sizeof(strtime), "(+ %d)", standings->increase[pnum]);
if (standings->numplayers > NUMFORNEWCOLUMN)
V_DrawRightAlignedThinString(x+135+gutter, y-1, V_6WIDTHSPACE, strtime);
@@ -370,7 +385,7 @@ static void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 x, INT32 hilicol)
V_DrawRightAlignedString(x+120+gutter, y, 0, strtime);
}
snprintf(strtime, sizeof strtime, "%d", standings->val[i]);
snprintf(strtime, sizeof(strtime), "%d", standings->val[i]);
if (standings->numplayers > NUMFORNEWCOLUMN)
V_DrawRightAlignedThinString(x+152+gutter, y-1, V_6WIDTHSPACE, strtime);
@@ -385,9 +400,9 @@ static void Y_PlayerStandingsDrawer(y_data_t *standings, INT32 x, INT32 hilicol)
{
if (intertype == int_race)
{
snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(standings->val[i], true),
snprintf(strtime, sizeof(strtime), "%i'%02i\"%02i", G_TicsToMinutes(standings->val[i], true),
G_TicsToSeconds(standings->val[i]), G_TicsToCentiseconds(standings->val[i]));
strtime[sizeof strtime - 1] = '\0';
strtime[sizeof(strtime) - 1] = '\0';
if (standings->numplayers > NUMFORNEWCOLUMN)
V_DrawRightAlignedThinString(x+152+gutter, y-1, V_6WIDTHSPACE, strtime);
@@ -652,15 +667,16 @@ static void Y_UpdateRecordReplays(void)
if ((gpath = malloc(glen)) == NULL)
I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_chooseskin.string);
snprintf(gpath, glen, "%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
snprintf(lastdemo, sizeof(lastdemo)-1, "%s-%s-last.lmp", gpath, cv_chooseskin.string);
if (FIL_FileExists(lastdemo))
{
UINT8 *buf;
size_t len = FIL_ReadFile(lastdemo, &buf);
snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, cv_chooseskin.string);
snprintf(bestdemo, sizeof(bestdemo)-1, "%s-%s-time-best.lmp", gpath, cv_chooseskin.string);
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
{ // Better time, save this demo.
if (FIL_FileExists(bestdemo))
@@ -669,7 +685,7 @@ static void Y_UpdateRecordReplays(void)
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
}
snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string);
snprintf(bestdemo, sizeof(bestdemo)-1, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string);
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))
{ // Better lap time, save this demo.
if (FIL_FileExists(bestdemo))
@@ -1499,12 +1515,12 @@ void Y_StartVote(void)
{
if (mapheaderinfo[votelevels[i][0]]->actnum[0])
snprintf(levelinfo[i].str,
sizeof levelinfo[i].str,
sizeof(levelinfo[i].str),
"%s %s",
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum);
else
snprintf(levelinfo[i].str,
sizeof levelinfo[i].str,
sizeof(levelinfo[i].str),
"%s",
mapheaderinfo[votelevels[i][0]]->lvlttl);
}
@@ -1512,12 +1528,12 @@ void Y_StartVote(void)
{
if (mapheaderinfo[votelevels[i][0]]->actnum[0])
snprintf(levelinfo[i].str,
sizeof levelinfo[i].str,
sizeof(levelinfo[i].str),
"%s %s %s",
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl, mapheaderinfo[votelevels[i][0]]->actnum);
else
snprintf(levelinfo[i].str,
sizeof levelinfo[i].str,
sizeof(levelinfo[i].str),
"%s %s",
mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl);
}