Merge branch 'udmf-linedef-executors' into udmf-executor-triggers

This commit is contained in:
MascaraSnake 2021-12-03 19:26:46 +01:00
commit 87a6528f00
59 changed files with 2106 additions and 1466 deletions

View file

@ -78,7 +78,7 @@ NONX86 = $(shell test "`echo $(CROSS_COMPILE_HOST) | grep 'i[3-6]86'`" || echo "
MAKEARGS = $(OS) $(NONX86) $(PREFIX) EXENAME=$(EXENAME) DBGNAME=$(DBGNAME) NOOBJDUMP=1 # SDL_PKGCONFIG=sdl2 PNG_PKGCONFIG=libpng MAKEARGS = $(OS) $(NONX86) $(PREFIX) EXENAME=$(EXENAME) DBGNAME=$(DBGNAME) NOOBJDUMP=1 # SDL_PKGCONFIG=sdl2 PNG_PKGCONFIG=libpng
MENUFILE1 = ?package($(PACKAGE)):needs="X11" section="$(SECTION)" MENUFILE1 = ?package($(PACKAGE)):needs="X11" section="$(SECTION)"
MENUFILE2 = title="$(TITLE)" command="/$(PKGDIR)/$(PACKAGE)" MENUFILE2 = title="$(TITLE)" command="/$(PKGDIR)/$(PACKAGE)"
BINDIR := $(DIR)/bin/Linux/Release BINDIR := $(DIR)/bin/
# FIXME pkg-config dir hacks # FIXME pkg-config dir hacks
# Launchpad doesn't need this; it actually makes i386 builds fail due to cross-compile # Launchpad doesn't need this; it actually makes i386 builds fail due to cross-compile

View file

@ -776,7 +776,6 @@ linedeftypes
{ {
title = "Make FOF Bouncy"; title = "Make FOF Bouncy";
prefix = "(76)"; prefix = "(76)";
flags16384text = "[14] Dampen";
} }
} }
@ -1999,7 +1998,7 @@ linedeftypes
title = "Set Tagged Sector's Floor Height/Texture"; title = "Set Tagged Sector's Floor Height/Texture";
prefix = "(400)"; prefix = "(400)";
flags8text = "[3] Set delay by backside sector"; flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Keep floor flat"; flags64text = "[6] Don't change floor texture";
} }
401 401
@ -2007,7 +2006,7 @@ linedeftypes
title = "Set Tagged Sector's Ceiling Height/Texture"; title = "Set Tagged Sector's Ceiling Height/Texture";
prefix = "(401)"; prefix = "(401)";
flags8text = "[3] Set delay by backside sector"; flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Keep floor flat"; flags64text = "[6] Don't change ceiling texture";
} }
402 402
@ -2118,7 +2117,7 @@ linedeftypes
prefix = "(403)"; prefix = "(403)";
flags2text = "[1] Trigger linedef executor"; flags2text = "[1] Trigger linedef executor";
flags8text = "[3] Set delay by backside sector"; flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Change floor flat"; flags64text = "[6] Change floor texture";
} }
404 404
@ -2127,7 +2126,7 @@ linedeftypes
prefix = "(404)"; prefix = "(404)";
flags2text = "[1] Trigger linedef executor"; flags2text = "[1] Trigger linedef executor";
flags8text = "[3] Set delay by backside sector"; flags8text = "[3] Set delay by backside sector";
flags64text = "[6] Change ceiling flat"; flags64text = "[6] Change ceiling texture";
} }
405 405

View file

@ -1994,12 +1994,6 @@ udmf
{ {
title = "Bounce strength"; title = "Bounce strength";
} }
arg2
{
title = "Dampen?";
type = 11;
enum = "noyes";
}
} }
} }

View file

@ -35,8 +35,6 @@ ifndef GCC295
WFLAGS+=-Wendif-labels WFLAGS+=-Wendif-labels
endif endif
ifdef GCC41 ifdef GCC41
WFLAGS+=-Wdeclaration-after-statement
WFLAGS+=-Wno-error=declaration-after-statement
WFLAGS+=-Wshadow WFLAGS+=-Wshadow
endif endif
#WFLAGS+=-Wlarger-than-%len% #WFLAGS+=-Wlarger-than-%len%

View file

@ -8,6 +8,11 @@ else
EXENAME?=srb2win64.exe EXENAME?=srb2win64.exe
endif endif
# disable dynamicbase if under msys2
ifdef MSYSTEM
libs+=-Wl,--disable-dynamicbase
endif
sources+=win32/Srb2win.rc sources+=win32/Srb2win.rc
opts+=-DSTDC_HEADERS opts+=-DSTDC_HEADERS
libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32 libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32

View file

@ -484,6 +484,19 @@ void CON_Init(void)
Unlock_state(); Unlock_state();
} }
} }
void CON_StartRefresh(void)
{
if (con_startup)
con_refresh = true;
}
void CON_StopRefresh(void)
{
if (con_startup)
con_refresh = false;
}
// Console input initialization // Console input initialization
// //
static void CON_InputInit(void) static void CON_InputInit(void)

View file

@ -16,6 +16,9 @@
void CON_Init(void); void CON_Init(void);
void CON_StartRefresh(void);
void CON_StopRefresh(void);
boolean CON_Responder(event_t *ev); boolean CON_Responder(event_t *ev);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS

View file

@ -128,10 +128,14 @@ static UINT8 localtextcmd[MAXTEXTCMD];
static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen static UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen
static tic_t neededtic; static tic_t neededtic;
SINT8 servernode = 0; // the number of the server node SINT8 servernode = 0; // the number of the server node
/// \brief do we accept new players? /// \brief do we accept new players?
/// \todo WORK! /// \todo WORK!
boolean acceptnewnode = true; boolean acceptnewnode = true;
static boolean serverisfull = false; //lets us be aware if the server was full after we check files, but before downloading, so we can ask if the user still wants to download or not
static tic_t firstconnectattempttime = 0;
// engine // engine
// Must be a power of two // Must be a power of two
@ -511,18 +515,24 @@ static INT16 Consistancy(void);
typedef enum typedef enum
{ {
CL_SEARCHING, CL_SEARCHING,
CL_CHECKFILES,
CL_DOWNLOADFILES, CL_DOWNLOADFILES,
CL_ASKJOIN, CL_ASKJOIN,
CL_LOADFILES,
CL_WAITJOINRESPONSE, CL_WAITJOINRESPONSE,
CL_DOWNLOADSAVEGAME, CL_DOWNLOADSAVEGAME,
CL_CONNECTED, CL_CONNECTED,
CL_ABORTED CL_ABORTED,
CL_ASKFULLFILELIST,
CL_CONFIRMCONNECT
} cl_mode_t; } cl_mode_t;
static void GetPackets(void); static void GetPackets(void);
static cl_mode_t cl_mode = CL_SEARCHING; static cl_mode_t cl_mode = CL_SEARCHING;
static UINT16 cl_lastcheckedfilecount = 0; // used for full file list
#ifndef NONET #ifndef NONET
#define SNAKE_SPEED 5 #define SNAKE_SPEED 5
@ -920,6 +930,8 @@ static void Snake_Draw(void)
INT16 i; INT16 i;
// Background // Background
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawFlatFill( V_DrawFlatFill(
SNAKE_LEFT_X + SNAKE_BORDER_SIZE, SNAKE_LEFT_X + SNAKE_BORDER_SIZE,
SNAKE_TOP_Y + SNAKE_BORDER_SIZE, SNAKE_TOP_Y + SNAKE_BORDER_SIZE,
@ -1021,6 +1033,13 @@ static void Snake_Draw(void)
); );
} }
static void CL_DrawConnectionStatusBox(void)
{
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1);
if (cl_mode != CL_CONFIRMCONNECT)
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
}
// //
// CL_DrawConnectionStatus // CL_DrawConnectionStatus
// //
@ -1031,28 +1050,32 @@ static inline void CL_DrawConnectionStatus(void)
INT32 ccstime = I_GetTime(); INT32 ccstime = I_GetTime();
// Draw background fade // Draw background fade
if (!menuactive) // menu already draws its own fade V_DrawFadeScreen(0xFF00, 16); // force default
V_DrawFadeScreen(0xFF00, 16); // force default
// Draw the bottom box. if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES)
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
if (cl_mode != CL_DOWNLOADFILES)
{ {
INT32 i, animtime = ((ccstime / 4) & 15) + 16; INT32 i, animtime = ((ccstime / 4) & 15) + 16;
UINT8 palstart = (cl_mode == CL_SEARCHING) ? 32 : 96; UINT8 palstart;
// 15 pal entries total.
const char *cltext; const char *cltext;
// Draw the bottom box.
CL_DrawConnectionStatusBox();
if (cl_mode == CL_SEARCHING)
palstart = 32; // Red
else if (cl_mode == CL_CONFIRMCONNECT)
palstart = 48; // Orange
else
palstart = 96; // Green
if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1)) if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1))
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i) // 15 pal entries total.
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15)); V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15));
switch (cl_mode) switch (cl_mode)
{ {
case CL_DOWNLOADSAVEGAME: case CL_DOWNLOADSAVEGAME:
if (lastfilenum != -1) if (fileneeded && lastfilenum != -1)
{ {
UINT32 currentsize = fileneeded[lastfilenum].currentsize; UINT32 currentsize = fileneeded[lastfilenum].currentsize;
UINT32 totalsize = fileneeded[lastfilenum].totalsize; UINT32 totalsize = fileneeded[lastfilenum].totalsize;
@ -1076,9 +1099,22 @@ static inline void CL_DrawConnectionStatus(void)
else else
cltext = M_GetText("Waiting to download game state..."); cltext = M_GetText("Waiting to download game state...");
break; break;
case CL_ASKFULLFILELIST:
case CL_CHECKFILES:
cltext = M_GetText("Checking server addon list...");
break;
case CL_CONFIRMCONNECT:
cltext = "";
break;
case CL_LOADFILES:
cltext = M_GetText("Loading server addons...");
break;
case CL_ASKJOIN: case CL_ASKJOIN:
case CL_WAITJOINRESPONSE: case CL_WAITJOINRESPONSE:
cltext = M_GetText("Requesting to join..."); if (serverisfull)
cltext = M_GetText("Server full, waiting for a slot...");
else
cltext = M_GetText("Requesting to join...");
break; break;
default: default:
cltext = M_GetText("Connecting to server..."); cltext = M_GetText("Connecting to server...");
@ -1088,14 +1124,51 @@ static inline void CL_DrawConnectionStatus(void)
} }
else else
{ {
if (lastfilenum != -1) if (cl_mode == CL_LOADFILES)
{
INT32 totalfileslength;
INT32 loadcompletednum = 0;
INT32 i;
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
//ima just count files here
if (fileneeded)
{
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_OPEN)
loadcompletednum++;
}
// Loading progress
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, "Loading server addons...");
totalfileslength = (INT32)((loadcompletednum/(double)(fileneedednum)) * 256);
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1);
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111);
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, totalfileslength, 8, 96);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
va(" %2u/%2u Files",loadcompletednum,fileneedednum));
}
else if (lastfilenum != -1)
{ {
INT32 dldlength; INT32 dldlength;
static char tempname[28]; static char tempname[28];
fileneeded_t *file = &fileneeded[lastfilenum]; fileneeded_t *file;
char *filename = file->filename; char *filename;
Snake_Draw(); if (snake)
Snake_Draw();
// Draw the bottom box.
CL_DrawConnectionStatusBox();
if (fileneeded)
{
file = &fileneeded[lastfilenum];
filename = file->filename;
}
else
return;
Net_GetNetStat(); Net_GetNetStat();
dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256); dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256);
@ -1128,20 +1201,32 @@ static inline void CL_DrawConnectionStatus(void)
va("%3.1fK/s ", ((double)getbps)/1024)); va("%3.1fK/s ", ((double)getbps)/1024));
} }
else else
{
if (snake)
Snake_Draw();
CL_DrawConnectionStatusBox();
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP, V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP,
M_GetText("Waiting to download files...")); M_GetText("Waiting to download files..."));
}
} }
} }
#endif #endif
static boolean CL_AskFileList(INT32 firstfile)
{
netbuffer->packettype = PT_TELLFILESNEEDED;
netbuffer->u.filesneedednum = firstfile;
return HSendPacket(servernode, false, 0, sizeof (INT32));
}
/** Sends a special packet to declare how many players in local /** Sends a special packet to declare how many players in local
* Used only in arbitratrenetstart() * Used only in arbitratrenetstart()
* Sends a PT_CLIENTJOIN packet to the server * Sends a PT_CLIENTJOIN packet to the server
* *
* \return True if the packet was successfully sent * \return True if the packet was successfully sent
* \todo Improve the description... * \todo Improve the description...
* Because to be honest, I have no idea what arbitratrenetstart is...
* Is it even used...?
* *
*/ */
static boolean CL_SendJoin(void) static boolean CL_SendJoin(void)
@ -1240,7 +1325,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
sizeof netbuffer->u.serverinfo.gametypename); sizeof netbuffer->u.serverinfo.gametypename);
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated; netbuffer->u.serverinfo.flags = (dedicated ? SV_DEDICATED : 0);
strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, strncpy(netbuffer->u.serverinfo.servername, cv_servername.string,
MAXSERVERNAME); MAXSERVERNAME);
strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7);
@ -1275,7 +1360,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
if (mapheaderinfo[gamemap-1]) if (mapheaderinfo[gamemap-1])
netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum; netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum;
p = PutFileNeeded(); p = PutFileNeeded(0);
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u));
} }
@ -1526,6 +1611,8 @@ static void CL_LoadReceivedSavegame(boolean reloading)
size_t length, decompressedlen; size_t length, decompressedlen;
char tmpsave[256]; char tmpsave[256];
FreeFileNeeded();
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
length = FIL_ReadFile(tmpsave, &savebuffer); length = FIL_ReadFile(tmpsave, &savebuffer);
@ -1838,12 +1925,162 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
#endif // ifndef NONET #endif // ifndef NONET
static const char * InvalidServerReason (INT32 i) static void M_ConfirmConnect(event_t *ev)
{
#ifndef NONET
if (ev->type == ev_keydown)
{
if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER)
{
if (totalfilesrequestednum > 0)
{
if (CL_SendFileRequest())
{
cl_mode = CL_DOWNLOADFILES;
Snake_Initialise();
}
}
else
cl_mode = CL_LOADFILES;
M_ClearMenus(true);
}
else if (ev->key == 'n' || ev->key == KEY_ESCAPE)
{
cl_mode = CL_ABORTED;
M_ClearMenus(true);
}
}
#else
(void)ev;
#endif
}
static boolean CL_FinishedFileList(void)
{
INT32 i;
char *downloadsize = NULL;
//CONS_Printf(M_GetText("Checking files...\n"));
i = CL_CheckFiles();
if (i == 4) // still checking ...
{
return true;
}
else if (i == 3) // too many files
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have too many WAD files loaded\n"
"to add ones the server is using.\n"
"Please restart SRB2 before connecting.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 2) // cannot join for some reason
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have the wrong addons loaded.\n\n"
"To play on this server, restart\n"
"the game and don't load any addons.\n"
"SRB2 will automatically add\n"
"everything you need when you join.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 1)
{
if (serverisfull)
{
M_StartMessage(M_GetText(
"This server is full!\n"
"\n"
"You may load server addons (if any), and wait for a slot.\n"
"\n"
"Press ENTER to continue\nor ESC to cancel.\n\n"
), M_ConfirmConnect, MM_EVENTHANDLER);
cl_mode = CL_CONFIRMCONNECT;
curfadevalue = 0;
}
else
cl_mode = CL_LOADFILES;
}
else
{
// must download something
// can we, though?
if (!CL_CheckDownloadable()) // nope!
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"An error occured when trying to\n"
"download missing addons.\n"
"(This is almost always a problem\n"
"with the server, not your game.)\n\n"
"See the console or log file\n"
"for additional details.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
#ifndef NONET
downloadcompletednum = 0;
downloadcompletedsize = 0;
totalfilesrequestednum = 0;
totalfilesrequestedsize = 0;
if (fileneeded == NULL)
I_Error("CL_FinishedFileList: fileneeded == NULL");
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
{
totalfilesrequestednum++;
totalfilesrequestedsize += fileneeded[i].totalsize;
}
if (totalfilesrequestedsize>>20 >= 100)
downloadsize = Z_StrDup(va("%uM",totalfilesrequestedsize>>20));
else
downloadsize = Z_StrDup(va("%uK",totalfilesrequestedsize>>10));
#endif
if (serverisfull)
M_StartMessage(va(M_GetText(
"This server is full!\n"
"Download of %s additional content\nis required to join.\n"
"\n"
"You may download, load server addons,\nand wait for a slot.\n"
"\n"
"Press ENTER to continue\nor ESC to cancel.\n"
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
else
M_StartMessage(va(M_GetText(
"Download of %s additional content\nis required to join.\n"
"\n"
"Press ENTER to continue\nor ESC to cancel.\n"
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
Z_Free(downloadsize);
cl_mode = CL_CONFIRMCONNECT;
curfadevalue = 0;
}
return true;
}
static const char * InvalidServerReason (serverinfo_pak *info)
{ {
#define EOT "\nPress ESC\n" #define EOT "\nPress ESC\n"
serverinfo_pak *info = &serverlist[i].info;
/* magic number for new packet format */ /* magic number for new packet format */
if (info->_255 != 255) if (info->_255 != 255)
{ {
@ -1936,86 +2173,44 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
if (client) if (client)
{ {
const char *reason = InvalidServerReason(i); serverinfo_pak *info = &serverlist[i].info;
// Quit here rather than downloading files if (info->refusereason == REFUSE_SLOTS_FULL)
// and being refused later. serverisfull = true;
if (reason)
{
char *message = Z_StrDup(reason);
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(message, NULL, MM_NOTHING);
Z_Free(message);
return false;
}
D_ParseFileneeded(serverlist[i].info.fileneedednum,
serverlist[i].info.fileneeded);
CONS_Printf(M_GetText("Checking files...\n"));
i = CL_CheckFiles();
if (i == 3) // too many files
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have too many WAD files loaded\n"
"to add ones the server is using.\n"
"Please restart SRB2 before connecting.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 2) // cannot join for some reason
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"You have the wrong addons loaded.\n\n"
"To play on this server, restart\n"
"the game and don't load any addons.\n"
"SRB2 will automatically add\n"
"everything you need when you join.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
else if (i == 1)
cl_mode = CL_ASKJOIN;
else else
{ {
// must download something const char *reason = InvalidServerReason(info);
// can we, though?
if (!CL_CheckDownloadable()) // nope! // Quit here rather than downloading files
// and being refused later.
if (reason)
{ {
char *message = Z_StrDup(reason);
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_StartTitle();
M_StartMessage(M_GetText( M_StartMessage(message, NULL, MM_NOTHING);
"You cannot connect to this server\n" Z_Free(message);
"because you cannot download the files\n"
"that you are missing from the server.\n\n"
"See the console or log file for\n"
"more details.\n\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false; return false;
} }
// no problem if can't send packet, we will retry later
if (CL_SendFileRequest())
{
cl_mode = CL_DOWNLOADFILES;
#ifndef NONET
Snake_Initialise();
#endif
}
} }
D_ParseFileneeded(info->fileneedednum, info->fileneeded, 0);
if (info->flags & SV_LOTSOFADDONS)
{
cl_mode = CL_ASKFULLFILELIST;
cl_lastcheckedfilecount = 0;
return true;
}
cl_mode = CL_CHECKFILES;
} }
else else
{
cl_mode = CL_ASKJOIN; // files need not be checked for the server. cl_mode = CL_ASKJOIN; // files need not be checked for the server.
*asksent = 0;
}
return true; return true;
} }
@ -2061,6 +2256,22 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
return false; return false;
break; break;
case CL_ASKFULLFILELIST:
if (cl_lastcheckedfilecount == UINT16_MAX) // All files retrieved
cl_mode = CL_CHECKFILES;
else if (fileneedednum != cl_lastcheckedfilecount || I_GetTime() >= *asksent)
{
if (CL_AskFileList(fileneedednum))
{
cl_lastcheckedfilecount = fileneedednum;
*asksent = I_GetTime() + NEWTICRATE;
}
}
break;
case CL_CHECKFILES:
if (!CL_FinishedFileList())
return false;
break;
case CL_DOWNLOADFILES: case CL_DOWNLOADFILES:
waitmore = false; waitmore = false;
for (i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
@ -2081,21 +2292,51 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
} }
#endif #endif
cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now cl_mode = CL_LOADFILES;
/* FALLTHRU */ break;
case CL_LOADFILES:
if (CL_LoadServerFiles())
{
FreeFileNeeded();
*asksent = 0; //This ensure the first join ask is right away
firstconnectattempttime = I_GetTime();
cl_mode = CL_ASKJOIN;
}
break;
case CL_ASKJOIN: case CL_ASKJOIN:
CL_LoadServerFiles(); if (firstconnectattempttime + NEWTICRATE*300 < I_GetTime() && !server)
{
CONS_Printf(M_GetText("5 minute wait time exceeded.\n"));
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
D_QuitNetGame();
CL_Reset();
D_StartTitle();
M_StartMessage(M_GetText(
"5 minute wait time exceeded.\n"
"You may retry connection.\n"
"\n"
"Press ESC\n"
), NULL, MM_NOTHING);
return false;
}
#ifndef NONET #ifndef NONET
// prepare structures to save the file // prepare structures to save the file
// WARNING: this can be useless in case of server not in GS_LEVEL // WARNING: this can be useless in case of server not in GS_LEVEL
// but since the network layer doesn't provide ordered packets... // but since the network layer doesn't provide ordered packets...
CL_PrepareDownloadSaveGame(tmpsave); CL_PrepareDownloadSaveGame(tmpsave);
#endif #endif
if (CL_SendJoin()) if (I_GetTime() >= *asksent && CL_SendJoin())
{
*asksent = I_GetTime() + NEWTICRATE*3;
cl_mode = CL_WAITJOINRESPONSE; cl_mode = CL_WAITJOINRESPONSE;
}
break;
case CL_WAITJOINRESPONSE:
if (I_GetTime() >= *asksent)
{
cl_mode = CL_ASKJOIN;
}
break; break;
#ifndef NONET #ifndef NONET
case CL_DOWNLOADSAVEGAME: case CL_DOWNLOADSAVEGAME:
// At this state, the first (and only) needed file is the gamestate // At this state, the first (and only) needed file is the gamestate
@ -2109,8 +2350,8 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
break; break;
#endif #endif
case CL_WAITJOINRESPONSE:
case CL_CONNECTED: case CL_CONNECTED:
case CL_CONFIRMCONNECT: //logic is handled by M_ConfirmConnect
default: default:
break; break;
@ -2118,7 +2359,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
case CL_ABORTED: case CL_ABORTED:
cl_mode = CL_SEARCHING; cl_mode = CL_SEARCHING;
return false; return false;
} }
GetPackets(); GetPackets();
@ -2128,13 +2368,19 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
if (*oldtic != I_GetTime()) if (*oldtic != I_GetTime())
{ {
I_OsPolling(); I_OsPolling();
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
G_MapEventsToControls(&events[eventtail]);
if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1]) if (cl_mode == CL_CONFIRMCONNECT)
D_ProcessEvents(); //needed for menu system to receive inputs
else
{
for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1))
G_MapEventsToControls(&events[eventtail]);
}
if (gamekeydown[KEY_ESCAPE] || gamekeydown[KEY_JOY1+1] || cl_mode == CL_ABORTED)
{ {
CONS_Printf(M_GetText("Network game synchronization aborted.\n")); CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
#ifndef NONET #ifndef NONET
if (snake) if (snake)
@ -2167,13 +2413,20 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
#ifndef NONET #ifndef NONET
if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)
{ {
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADSAVEGAME) if (!snake)
{ {
F_MenuPresTicker(true); // title sky F_MenuPresTicker(true); // title sky
F_TitleScreenTicker(true); F_TitleScreenTicker(true);
F_TitleScreenDrawer(); F_TitleScreenDrawer();
} }
CL_DrawConnectionStatus(); CL_DrawConnectionStatus();
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex);
#endif
M_Drawer(); //Needed for drawing messageboxes on the connection screen
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex);
#endif
I_UpdateNoVsync(); // page flip or blit buffer I_UpdateNoVsync(); // page flip or blit buffer
if (moviemode) if (moviemode)
M_SaveFrame(); M_SaveFrame();
@ -2235,8 +2488,10 @@ static void CL_ConnectToServer(void)
ClearAdminPlayers(); ClearAdminPlayers();
pnumnodes = 1; pnumnodes = 1;
oldtic = I_GetTime() - 1; oldtic = I_GetTime() - 1;
#ifndef NONET #ifndef NONET
asksent = (tic_t) - TICRATE; asksent = (tic_t) - TICRATE;
firstconnectattempttime = I_GetTime();
i = SL_SearchServer(servernode); i = SL_SearchServer(servernode);
@ -2676,8 +2931,16 @@ void CL_Reset(void)
SV_ResetServer(); SV_ResetServer();
// make sure we don't leave any fileneeded gunk over from a failed join // make sure we don't leave any fileneeded gunk over from a failed join
FreeFileNeeded();
fileneedednum = 0; fileneedednum = 0;
memset(fileneeded, 0, sizeof(fileneeded));
#ifndef NONET
totalfilesrequestednum = 0;
totalfilesrequestedsize = 0;
#endif
firstconnectattempttime = 0;
serverisfull = false;
connectiontimeout = (tic_t)cv_nettimeout.value; //reset this temporary hack
// D_StartTitle should get done now, but the calling function will handle it // D_StartTitle should get done now, but the calling function will handle it
} }
@ -2932,6 +3195,34 @@ static void Command_Kick(void)
else else
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
} }
static void Command_ResendGamestate(void)
{
SINT8 playernum;
if (COM_Argc() == 1)
{
CONS_Printf(M_GetText("resendgamestate <playername/playernum>: resend the game state to a player\n"));
return;
}
else if (client)
{
CONS_Printf(M_GetText("Only the server can use this.\n"));
return;
}
playernum = nametonum(COM_Argv(1));
if (playernum == -1 || playernum == 0)
return;
// Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
if (!HSendPacket(playernode[playernum], true, 0, 0))
{
CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n"));
return;
}
}
#endif #endif
static void Got_KickCmd(UINT8 **p, INT32 playernum) static void Got_KickCmd(UINT8 **p, INT32 playernum)
@ -3139,34 +3430,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
CL_RemovePlayer(pnum, kickreason); CL_RemovePlayer(pnum, kickreason);
} }
static void Command_ResendGamestate(void)
{
SINT8 playernum;
if (COM_Argc() == 1)
{
CONS_Printf(M_GetText("resendgamestate <playername/playernum>: resend the game state to a player\n"));
return;
}
else if (client)
{
CONS_Printf(M_GetText("Only the server can use this.\n"));
return;
}
playernum = nametonum(COM_Argv(1));
if (playernum == -1 || playernum == 0)
return;
// Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
if (!HSendPacket(playernode[playernum], true, 0, 0))
{
CONS_Alert(CONS_ERROR, M_GetText("A problem occured, please try again.\n"));
return;
}
}
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}}; static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL); consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL);
@ -3189,7 +3452,7 @@ consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_
consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL); consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
// Speed of file downloading (in packets per tic) // Speed of file downloading (in packets per tic)
static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}}; static CV_PossibleValue_t downloadspeed_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL); consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL);
static void Got_AddPlayer(UINT8 **p, INT32 playernum); static void Got_AddPlayer(UINT8 **p, INT32 playernum);
@ -3903,6 +4166,7 @@ static void HandleServerInfo(SINT8 node)
static void PT_WillResendGamestate(void) static void PT_WillResendGamestate(void)
{ {
#ifndef NONET
char tmpsave[256]; char tmpsave[256];
if (server || cl_redownloadinggamestate) if (server || cl_redownloadinggamestate)
@ -3925,10 +4189,12 @@ static void PT_WillResendGamestate(void)
CL_PrepareDownloadSaveGame(tmpsave); CL_PrepareDownloadSaveGame(tmpsave);
cl_redownloadinggamestate = true; cl_redownloadinggamestate = true;
#endif
} }
static void PT_CanReceiveGamestate(SINT8 node) static void PT_CanReceiveGamestate(SINT8 node)
{ {
#ifndef NONET
if (client || sendingsavegame[node]) if (client || sendingsavegame[node])
return; return;
@ -3936,6 +4202,9 @@ static void PT_CanReceiveGamestate(SINT8 node)
SV_SendSaveGame(node, true); // Resend a complete game state SV_SendSaveGame(node, true); // Resend a complete game state
resendingsavegame[node] = true; resendingsavegame[node] = true;
#else
(void)node;
#endif
} }
/** Handles a packet received from a node that isn't in game /** Handles a packet received from a node that isn't in game
@ -3962,31 +4231,40 @@ static void HandlePacketFromAwayNode(SINT8 node)
switch (netbuffer->packettype) switch (netbuffer->packettype)
{ {
case PT_ASKINFOVIAMS: case PT_ASKINFOVIAMS:
#if 0 Net_CloseConnection(node);
break;
case PT_TELLFILESNEEDED:
if (server && serverrunning) if (server && serverrunning)
{ {
INT32 clientnode; UINT8 *p;
if (ms_RoomId < 0) // ignore if we're not actually on the MS right now INT32 firstfile = netbuffer->u.filesneedednum;
{
Net_CloseConnection(node); // and yes, close connection netbuffer->packettype = PT_MOREFILESNEEDED;
return; netbuffer->u.filesneededcfg.first = firstfile;
} netbuffer->u.filesneededcfg.more = 0;
clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
if (clientnode != -1) p = PutFileNeeded(firstfile);
{
SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time)); HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u));
SV_SendPlayerInfo(clientnode); // Send extra info }
Net_CloseConnection(clientnode); else // Shouldn't get this if you aren't the server...?
// Don't close connection to MS... Net_CloseConnection(node);
} break;
else
Net_CloseConnection(node); // ...unless the IP address is not valid case PT_MOREFILESNEEDED:
if (server && serverrunning)
{ // But wait I thought I'm the server?
Net_CloseConnection(node);
break;
}
SERVERONLY
if (cl_mode == CL_ASKFULLFILELIST && netbuffer->u.filesneededcfg.first == fileneedednum)
{
D_ParseFileneeded(netbuffer->u.filesneededcfg.num, netbuffer->u.filesneededcfg.files, netbuffer->u.filesneededcfg.first);
if (!netbuffer->u.filesneededcfg.more)
cl_lastcheckedfilecount = UINT16_MAX; // Got the whole file list
} }
else
Net_CloseConnection(node); // you're not supposed to get it, so ignore it
#else
Net_CloseConnection(node);
#endif
break; break;
case PT_ASKINFO: case PT_ASKINFO:
@ -4012,13 +4290,24 @@ static void HandlePacketFromAwayNode(SINT8 node)
if (!reason) if (!reason)
I_Error("Out of memory!\n"); I_Error("Out of memory!\n");
D_QuitNetGame(); if (strstr(reason, "Maximum players reached"))
CL_Reset(); {
D_StartTitle(); serverisfull = true;
//Special timeout for when refusing due to player cap. The client will wait 3 seconds between join requests when waiting for a slot, so we need this to be much longer
//We set it back to the value of cv_nettimeout.value in CL_Reset
connectiontimeout = NEWTICRATE*7;
cl_mode = CL_ASKJOIN;
free(reason);
break;
}
M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"), M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
reason), NULL, MM_NOTHING); reason), NULL, MM_NOTHING);
D_QuitNetGame();
CL_Reset();
D_StartTitle();
free(reason); free(reason);
// Will be reset by caller. Signals refusal. // Will be reset by caller. Signals refusal.
@ -4222,8 +4511,10 @@ static void HandlePacketFromPlayer(SINT8 node)
// Check player consistancy during the level // Check player consistancy during the level
if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL
&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy) && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)
&& !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime() #ifndef NONET
&& !SV_ResendingSavegameToAnyone()) && !SV_ResendingSavegameToAnyone()
#endif
&& !resendingsavegame[node] && savegameresendcooldown[node] <= I_GetTime())
{ {
if (cv_resynchattempts.value) if (cv_resynchattempts.value)
{ {
@ -4974,16 +5265,23 @@ void TryRunTics(tic_t realtics)
// run the count * tics // run the count * tics
while (neededtic > gametic) while (neededtic > gametic)
{ {
boolean update_stats = !(paused || P_AutoPause());
DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic)); DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic));
ps_tictime = I_GetPreciseTime(); if (update_stats)
PS_START_TIMING(ps_tictime);
G_Ticker((gametic % NEWTICRATERATIO) == 0); G_Ticker((gametic % NEWTICRATERATIO) == 0);
ExtraDataTicker(); ExtraDataTicker();
gametic++; gametic++;
consistancy[gametic%BACKUPTICS] = Consistancy(); consistancy[gametic%BACKUPTICS] = Consistancy();
ps_tictime = I_GetPreciseTime() - ps_tictime; if (update_stats)
{
PS_STOP_TIMING(ps_tictime);
PS_UpdateTickStats();
}
// Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame. // Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame.
if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value) if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value)
@ -5127,9 +5425,11 @@ void NetUpdate(void)
if (client) if (client)
{ {
#ifndef NONET
// If the client just finished redownloading the game state, load it // If the client just finished redownloading the game state, load it
if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND) if (cl_redownloadinggamestate && fileneeded[0].status == FS_FOUND)
CL_ReloadReceivedSavegame(); CL_ReloadReceivedSavegame();
#endif
CL_SendClientCmd(); // Send tic cmd CL_SendClientCmd(); // Send tic cmd
hu_redownloadinggamestate = cl_redownloadinggamestate; hu_redownloadinggamestate = cl_redownloadinggamestate;

View file

@ -94,6 +94,9 @@ typedef enum
PT_LOGIN, // Login attempt from the client. PT_LOGIN, // Login attempt from the client.
PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?"
PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)"
PT_PING, // Packet sent to tell clients the other client's latency to server. PT_PING, // Packet sent to tell clients the other client's latency to server.
NUMPACKETTYPE NUMPACKETTYPE
} packettype_t; } packettype_t;
@ -198,6 +201,9 @@ typedef struct
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME]; char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
} ATTRPACK clientconfig_pak; } ATTRPACK clientconfig_pak;
#define SV_DEDICATED 0x40 // server is dedicated
#define SV_LOTSOFADDONS 0x20 // flag used to ask for full file list in d_netfil
enum { enum {
REFUSE_JOINS_DISABLED = 1, REFUSE_JOINS_DISABLED = 1,
REFUSE_SLOTS_FULL, REFUSE_SLOTS_FULL,
@ -225,7 +231,7 @@ typedef struct
char gametypename[24]; char gametypename[24];
UINT8 modifiedgame; UINT8 modifiedgame;
UINT8 cheatsenabled; UINT8 cheatsenabled;
UINT8 isdedicated; UINT8 flags;
UINT8 fileneedednum; UINT8 fileneedednum;
tic_t time; tic_t time;
tic_t leveltime; tic_t leveltime;
@ -279,6 +285,14 @@ typedef struct
UINT8 ctfteam; UINT8 ctfteam;
} ATTRPACK plrconfig; } ATTRPACK plrconfig;
typedef struct
{
INT32 first;
UINT8 num;
UINT8 more;
UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
} ATTRPACK filesneededconfig_pak;
// //
// Network packet data // Network packet data
// //
@ -308,6 +322,8 @@ typedef struct
msaskinfo_pak msaskinfo; // 22 bytes msaskinfo_pak msaskinfo; // 22 bytes
plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?) plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?)
plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
INT32 filesneedednum; // 4 bytes
filesneededconfig_pak filesneededcfg; // ??? bytes
UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
} u; // This is needed to pack diff packet types data together } u; // This is needed to pack diff packet types data together
} ATTRPACK doomdata_t; } ATTRPACK doomdata_t;

View file

@ -65,7 +65,7 @@
#include "m_cond.h" // condition initialization #include "m_cond.h" // condition initialization
#include "fastcmp.h" #include "fastcmp.h"
#include "keys.h" #include "keys.h"
#include "filesrch.h" // refreshdirmenu, mainwadstally #include "filesrch.h" // refreshdirmenu
#include "g_input.h" // tutorial mode control scheming #include "g_input.h" // tutorial mode control scheming
#include "m_perfstats.h" #include "m_perfstats.h"
@ -96,11 +96,8 @@ int SUBVERSION;
// platform independant focus loss // platform independant focus loss
UINT8 window_notinfocus = false; UINT8 window_notinfocus = false;
// static addfilelist_t startupwadfiles;
// DEMO LOOP static addfilelist_t startuppwads;
//
static char *startupwadfiles[MAX_WADFILES];
static char *startuppwads[MAX_WADFILES];
boolean devparm = false; // started game with -devparm boolean devparm = false; // started game with -devparm
@ -119,6 +116,9 @@ boolean midi_disabled = false;
boolean sound_disabled = false; boolean sound_disabled = false;
boolean digital_disabled = false; boolean digital_disabled = false;
//
// DEMO LOOP
//
boolean advancedemo; boolean advancedemo;
#ifdef DEBUGFILE #ifdef DEBUGFILE
INT32 debugload = 0; INT32 debugload = 0;
@ -272,7 +272,7 @@ void D_ProcessEvents(void)
if (eaten) if (eaten)
continue; // ate the event continue; // ate the event
if (!hooked && G_LuaResponder(ev)) if (!hooked && !CON_Ready() && G_LuaResponder(ev))
continue; continue;
G_Responder(ev); G_Responder(ev);
@ -476,7 +476,7 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value) if (!automapactive && !dedicated && cv_renderview.value)
{ {
ps_rendercalltime = I_GetPreciseTime(); PS_START_TIMING(ps_rendercalltime);
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD) if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{ {
topleft = screens[0] + viewwindowy*vid.width + viewwindowx; topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
@ -523,7 +523,7 @@ static void D_Display(void)
if (postimgtype2) if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2); V_DoPostProcessor(1, postimgtype2, postimgparam2);
} }
ps_rendercalltime = I_GetPreciseTime() - ps_rendercalltime; PS_STOP_TIMING(ps_rendercalltime);
} }
if (lastdraw) if (lastdraw)
@ -537,7 +537,7 @@ static void D_Display(void)
lastdraw = false; lastdraw = false;
} }
ps_uitime = I_GetPreciseTime(); PS_START_TIMING(ps_uitime);
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
@ -550,7 +550,7 @@ static void D_Display(void)
} }
else else
{ {
ps_uitime = I_GetPreciseTime(); PS_START_TIMING(ps_uitime);
} }
} }
@ -592,7 +592,7 @@ static void D_Display(void)
CON_Drawer(); CON_Drawer();
ps_uitime = I_GetPreciseTime() - ps_uitime; PS_STOP_TIMING(ps_uitime);
// //
// wipe update // wipe update
@ -678,9 +678,9 @@ static void D_Display(void)
M_DrawPerfStats(); M_DrawPerfStats();
} }
ps_swaptime = I_GetPreciseTime(); PS_START_TIMING(ps_swaptime);
I_FinishUpdate(); // page flip or blit buffer I_FinishUpdate(); // page flip or blit buffer
ps_swaptime = I_GetPreciseTime() - ps_swaptime; PS_STOP_TIMING(ps_swaptime);
} }
} }
@ -923,51 +923,68 @@ void D_StartTitle(void)
tutorialmode = false; tutorialmode = false;
} }
// #define REALLOC_FILE_LIST \
// D_AddFile if (list->files == NULL) \
// { \
static void D_AddFile(char **list, const char *file) list->files = calloc(sizeof(list->files), 2); \
{ list->numfiles = 1; \
size_t pnumwadfiles; } \
char *newfile; else \
{ \
index = list->numfiles; \
list->files = realloc(list->files, sizeof(list->files) * ((++list->numfiles) + 1)); \
if (list->files == NULL) \
I_Error("%s: No more free memory to add file %s", __FUNCTION__, file); \
}
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++) static void D_AddFile(addfilelist_t *list, const char *file)
; {
char *newfile;
size_t index = 0;
REALLOC_FILE_LIST
newfile = malloc(strlen(file) + 1); newfile = malloc(strlen(file) + 1);
if (!newfile) if (!newfile)
I_Error("No more free memory to AddFile %s",file); I_Error("D_AddFile: No more free memory to add file %s", file);
strcpy(newfile, file); strcpy(newfile, file);
list[pnumwadfiles] = newfile; list->files[index] = newfile;
} }
static void D_AddFolder(char **list, const char *file) static void D_AddFolder(addfilelist_t *list, const char *file)
{ {
size_t pnumwadfiles;
char *newfile; char *newfile;
size_t index = 0;
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++) REALLOC_FILE_LIST
;
newfile = malloc(strlen(file) + 2); // Path delimiter + NULL terminator newfile = malloc(strlen(file) + 2); // Path delimiter + NULL terminator
if (!newfile) if (!newfile)
I_Error("No more free memory to AddFolder %s",file); I_Error("D_AddFolder: No more free memory to add folder %s", file);
strcpy(newfile, file); strcpy(newfile, file);
strcat(newfile, PATHSEP); strcat(newfile, PATHSEP);
list[pnumwadfiles] = newfile; list->files[index] = newfile;
} }
static inline void D_CleanFile(char **list) #undef REALLOC_FILE_LIST
static inline void D_CleanFile(addfilelist_t *list)
{ {
size_t pnumwadfiles; if (list->files)
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
{ {
free(list[pnumwadfiles]); size_t pnumwadfiles = 0;
list[pnumwadfiles] = NULL;
for (; pnumwadfiles < list->numfiles; pnumwadfiles++)
free(list->files[pnumwadfiles]);
free(list->files);
list->files = NULL;
} }
list->numfiles = 0;
} }
///\brief Checks if a netgame URL is being handled, and changes working directory to the EXE's if so. ///\brief Checks if a netgame URL is being handled, and changes working directory to the EXE's if so.
@ -1051,7 +1068,7 @@ static void IdentifyVersion(void)
// Load the IWAD // Load the IWAD
if (srb2wad != NULL && FIL_ReadFileOK(srb2wad)) if (srb2wad != NULL && FIL_ReadFileOK(srb2wad))
D_AddFile(startupwadfiles, srb2wad); D_AddFile(&startupwadfiles, srb2wad);
else else
I_Error("srb2.pk3 not found! Expected in %s, ss file: %s\n", srb2waddir, srb2wad); I_Error("srb2.pk3 not found! Expected in %s, ss file: %s\n", srb2waddir, srb2wad);
@ -1062,14 +1079,14 @@ static void IdentifyVersion(void)
// checking in D_SRB2Main // checking in D_SRB2Main
// Add the maps // Add the maps
D_AddFile(startupwadfiles, va(pandf,srb2waddir,"zones.pk3")); D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "zones.pk3"));
// Add the players // Add the players
D_AddFile(startupwadfiles, va(pandf,srb2waddir, "player.dta")); D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "player.dta"));
#ifdef USE_PATCH_DTA #ifdef USE_PATCH_DTA
// Add our crappy patches to fix our bugs // Add our crappy patches to fix our bugs
D_AddFile(startupwadfiles, va(pandf,srb2waddir,"patch.pk3")); D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "patch.pk3"));
#endif #endif
#if !defined (HAVE_SDL) || defined (HAVE_MIXER) #if !defined (HAVE_SDL) || defined (HAVE_MIXER)
@ -1079,7 +1096,7 @@ static void IdentifyVersion(void)
const char *musicpath = va(pandf,srb2waddir,str);\ const char *musicpath = va(pandf,srb2waddir,str);\
int ms = W_VerifyNMUSlumps(musicpath, false); \ int ms = W_VerifyNMUSlumps(musicpath, false); \
if (ms == 1) \ if (ms == 1) \
D_AddFile(startupwadfiles, musicpath); \ D_AddFile(&startupwadfiles, musicpath); \
else if (ms == 0) \ else if (ms == 0) \
I_Error("File "str" has been modified with non-music/sound lumps"); \ I_Error("File "str" has been modified with non-music/sound lumps"); \
} }
@ -1269,9 +1286,9 @@ void D_SRB2Main(void)
else if (myargv[i][0] == '-' || myargv[i][0] == '+') else if (myargv[i][0] == '-' || myargv[i][0] == '+')
addontype = 0; addontype = 0;
else if (addontype == 1) else if (addontype == 1)
D_AddFile(startuppwads, myargv[i]); D_AddFile(&startuppwads, myargv[i]);
else if (addontype == 2) else if (addontype == 2)
D_AddFolder(startuppwads, myargv[i]); D_AddFolder(&startuppwads, myargv[i]);
} }
} }
@ -1310,8 +1327,8 @@ void D_SRB2Main(void)
// load wad, including the main wad file // load wad, including the main wad file
CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n");
W_InitMultipleFiles(startupwadfiles); W_InitMultipleFiles(&startupwadfiles);
D_CleanFile(startupwadfiles); D_CleanFile(&startupwadfiles);
#ifndef DEVELOP // md5s last updated 22/02/20 (ddmmyy) #ifndef DEVELOP // md5s last updated 22/02/20 (ddmmyy)
@ -1326,8 +1343,6 @@ void D_SRB2Main(void)
// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
#endif //ifndef DEVELOP #endif //ifndef DEVELOP
mainwadstally = packetsizetally; // technically not accurate atm, remember to port the two-stage -file process from kart in 2.2.x
cht_Init(); cht_Init();
//---------------------------------------------------- READY SCREEN //---------------------------------------------------- READY SCREEN
@ -1358,9 +1373,16 @@ void D_SRB2Main(void)
I_RegisterSysCommands(); I_RegisterSysCommands();
CONS_Printf("W_InitMultipleFiles(): Adding extra PWADs.\n"); CON_StopRefresh(); // Temporarily stop refreshing the screen for wad loading
W_InitMultipleFiles(startuppwads);
D_CleanFile(startuppwads); if (startuppwads.numfiles)
{
CONS_Printf("W_InitMultipleFiles(): Adding extra PWADs.\n");
W_InitMultipleFiles(&startuppwads);
D_CleanFile(&startuppwads);
}
CON_StartRefresh(); // Restart the refresh!
CONS_Printf("HU_LoadGraphics()...\n"); CONS_Printf("HU_LoadGraphics()...\n");
HU_LoadGraphics(); HU_LoadGraphics();

View file

@ -815,6 +815,8 @@ static const char *packettypename[NUMPACKETTYPE] =
"CLIENTJOIN", "CLIENTJOIN",
"NODETIMEOUT", "NODETIMEOUT",
"LOGIN", "LOGIN",
"TELLFILESNEEDED",
"MOREFILESNEEDED",
"PING" "PING"
}; };

View file

@ -47,6 +47,7 @@
#include "m_cond.h" #include "m_cond.h"
#include "m_anigif.h" #include "m_anigif.h"
#include "md5.h" #include "md5.h"
#include "m_perfstats.h"
#ifdef NETGAME_DEVMODE #ifdef NETGAME_DEVMODE
#define CV_RESTRICT CV_NETVAR #define CV_RESTRICT CV_NETVAR
@ -374,7 +375,14 @@ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL)
static CV_PossibleValue_t perfstats_cons_t[] = { static CV_PossibleValue_t perfstats_cons_t[] = {
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL); consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange);
static CV_PossibleValue_t ps_samplesize_cons_t[] = {
{1, "MIN"}, {1000, "MAX"}, {0, NULL}};
consvar_t cv_ps_samplesize = CVAR_INIT ("ps_samplesize", "1", CV_CALL, ps_samplesize_cons_t, PS_SampleSize_OnChange);
static CV_PossibleValue_t ps_descriptor_cons_t[] = {
{1, "Average"}, {2, "SD"}, {3, "Minimum"}, {4, "Maximum"}, {0, NULL}};
consvar_t cv_ps_descriptor = CVAR_INIT ("ps_descriptor", "Average", 0, ps_descriptor_cons_t, NULL);
consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL); consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL);
char timedemo_name[256]; char timedemo_name[256];
@ -867,6 +875,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_soundtest); CV_RegisterVar(&cv_soundtest);
CV_RegisterVar(&cv_perfstats); CV_RegisterVar(&cv_perfstats);
CV_RegisterVar(&cv_ps_samplesize);
CV_RegisterVar(&cv_ps_descriptor);
// ingame object placing // ingame object placing
COM_AddCommand("objectplace", Command_ObjectPlace_f); COM_AddCommand("objectplace", Command_ObjectPlace_f);
@ -3223,7 +3233,7 @@ static void Command_RunSOC(void)
static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum) static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
{ {
char filename[256]; char filename[256];
filestatus_t ncs = FS_NOTFOUND; filestatus_t ncs = FS_NOTCHECKED;
if (playernum != serverplayer && !IsPlayerAdmin(playernum)) if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{ {
@ -3347,10 +3357,9 @@ static void Command_Addfile(void)
break; break;
++p; ++p;
// check total packet size and no of files currently loaded // check no of files currently loaded
// See W_InitFile in w_wad.c // See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
{ {
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return; return;
@ -3379,6 +3388,9 @@ static void Command_Addfile(void)
for (i = 0; i < numwadfiles; i++) for (i = 0; i < numwadfiles; i++)
{ {
if (wadfiles[i]->type == RET_FOLDER)
continue;
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
{ {
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
@ -3469,10 +3481,9 @@ static void Command_Addfolder(void)
continue; continue;
} }
// check total packet size and no of files currently loaded // check no of files currently loaded
// See W_InitFile in w_wad.c // See W_LoadWadFile in w_wad.c
if ((numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + strlen(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
{ {
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn); CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
return; return;
@ -3534,7 +3545,7 @@ static void Command_Addfolder(void)
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
{ {
char filename[241]; char filename[241];
filestatus_t ncs = FS_NOTFOUND; filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16]; UINT8 md5sum[16];
boolean kick = false; boolean kick = false;
boolean toomany = false; boolean toomany = false;
@ -3559,9 +3570,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
return; return;
} }
// See W_InitFile in w_wad.c if (numwadfiles >= MAX_WADFILES)
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
toomany = true; toomany = true;
else else
ncs = findfile(filename,md5sum,true); ncs = findfile(filename,md5sum,true);
@ -3594,7 +3603,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum) static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
{ {
char path[241]; char path[241];
filestatus_t ncs = FS_NOTFOUND; filestatus_t ncs = FS_NOTCHECKED;
boolean kick = false; boolean kick = false;
boolean toomany = false; boolean toomany = false;
INT32 i,j; INT32 i,j;
@ -3619,9 +3628,7 @@ static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
return; return;
} }
// See W_InitFile in w_wad.c if (numwadfiles >= MAX_WADFILES)
if ((numwadfiles >= MAX_WADFILES)
|| ((packetsizetally + strlen(path) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
toomany = true; toomany = true;
else else
ncs = findfolder(path); ncs = findfolder(path);
@ -3652,7 +3659,7 @@ static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum) static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
{ {
char filename[241]; char filename[241];
filestatus_t ncs = FS_NOTFOUND; filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16]; UINT8 md5sum[16];
READSTRINGN(*cp, filename, 240); READSTRINGN(*cp, filename, 240);
@ -3700,7 +3707,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum) static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum)
{ {
char path[241]; char path[241];
filestatus_t ncs = FS_NOTFOUND; filestatus_t ncs = FS_NOTCHECKED;
READSTRINGN(*cp, path, 240); READSTRINGN(*cp, path, 240);
@ -3744,7 +3751,13 @@ static void Command_ListWADS_f(void)
{ {
INT32 i = numwadfiles; INT32 i = numwadfiles;
char *tempname; char *tempname;
CONS_Printf(M_GetText("There are %d wads loaded:\n"),numwadfiles);
#ifdef ENFORCE_WAD_LIMIT
CONS_Printf(M_GetText("There are %d/%d files loaded:\n"),numwadfiles,MAX_WADFILES);
#else
CONS_Printf(M_GetText("There are %d files loaded:\n"),numwadfiles);
#endif
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
{ {
nameonly(tempname = va("%s", wadfiles[i]->filename)); nameonly(tempname = va("%s", wadfiles[i]->filename));

View file

@ -73,6 +73,7 @@ extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange; extern consvar_t cv_scrambleonchange;
extern consvar_t cv_netstat; extern consvar_t cv_netstat;
extern consvar_t cv_nettimeout;
extern consvar_t cv_countdowntime; extern consvar_t cv_countdowntime;
extern consvar_t cv_runscripts; extern consvar_t cv_runscripts;
@ -110,6 +111,8 @@ extern consvar_t cv_skipmapcheck;
extern consvar_t cv_sleep; extern consvar_t cv_sleep;
extern consvar_t cv_perfstats; extern consvar_t cv_perfstats;
extern consvar_t cv_ps_samplesize;
extern consvar_t cv_ps_descriptor;
extern char timedemo_name[256]; extern char timedemo_name[256];
extern boolean timedemo_csv; extern boolean timedemo_csv;

View file

@ -52,7 +52,7 @@
#include <errno.h> #include <errno.h>
// Prototypes // Prototypes
static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid); static boolean AddFileToSendQueue(INT32 node, UINT8 fileid);
// Sender structure // Sender structure
typedef struct filetx_s typedef struct filetx_s
@ -87,7 +87,7 @@ static filetran_t transfer[MAXNETNODES];
// Receiver structure // Receiver structure
INT32 fileneedednum; // Number of files needed to join the server INT32 fileneedednum; // Number of files needed to join the server
fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files fileneeded_t *fileneeded; // List of needed files
static tic_t lasttimeackpacketsent = 0; static tic_t lasttimeackpacketsent = 0;
char downloaddir[512] = "DOWNLOAD"; char downloaddir[512] = "DOWNLOAD";
@ -105,6 +105,10 @@ static pauseddownload_t *pauseddownload = NULL;
#ifndef NONET #ifndef NONET
// for cl loading screen // for cl loading screen
INT32 lastfilenum = -1; INT32 lastfilenum = -1;
INT32 downloadcompletednum = 0;
UINT32 downloadcompletedsize = 0;
INT32 totalfilesrequestednum = 0;
UINT32 totalfilesrequestedsize = 0;
#endif #endif
luafiletransfer_t *luafiletransfers = NULL; luafiletransfer_t *luafiletransfers = NULL;
@ -113,25 +117,62 @@ boolean waitingforluafilecommand = false;
char luafiledir[256 + 16] = "luafiles"; char luafiledir[256 + 16] = "luafiles";
static UINT16 GetWadNumFromFileNeededId(UINT8 id)
{
UINT16 wadnum;
for (wadnum = mainwads; wadnum < numwadfiles; wadnum++)
{
if (!wadfiles[wadnum]->important)
continue;
if (id == 0)
return wadnum;
id--;
}
return UINT16_MAX;
}
/** Fills a serverinfo packet with information about wad files loaded. /** Fills a serverinfo packet with information about wad files loaded.
* *
* \todo Give this function a better name since it is in global scope. * \todo Give this function a better name since it is in global scope.
* Used to have size limiting built in - now handled via W_InitFile in w_wad.c * Used to have size limiting built in - now handled via W_InitFile in w_wad.c
* *
*/ */
UINT8 *PutFileNeeded(void) UINT8 *PutFileNeeded(UINT16 firstfile)
{ {
size_t i, count = 0; size_t i;
UINT8 *p = netbuffer->u.serverinfo.fileneeded; UINT8 count = 0;
UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded;
UINT8 *p = p_start;
char wadfilename[MAX_WADPATH] = ""; char wadfilename[MAX_WADPATH] = "";
UINT8 filestatus, folder; UINT8 filestatus, folder;
for (i = 0; i < numwadfiles; i++) for (i = mainwads; i < numwadfiles; i++) //mainwads, otherwise we start on the first mainwad
{ {
// If it has only music/sound lumps, don't put it in the list // If it has only music/sound lumps, don't put it in the list
if (!wadfiles[i]->important) if (!wadfiles[i]->important)
continue; continue;
if (firstfile)
{ // Skip files until we reach the first file.
firstfile--;
continue;
}
nameonly(strcpy(wadfilename, wadfiles[i]->filename));
// Look below at the WRITE macros to understand what these numbers mean.
if (p + 1 + 4 + min(strlen(wadfilename) + 1, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED)
{
// Too many files to send all at once
if (netbuffer->packettype == PT_MOREFILESNEEDED)
netbuffer->u.filesneededcfg.more = 1;
else
netbuffer->u.serverinfo.flags |= SV_LOTSOFADDONS;
break;
}
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
folder = (wadfiles[i]->type == RET_FOLDER); folder = (wadfiles[i]->type == RET_FOLDER);
@ -148,32 +189,53 @@ UINT8 *PutFileNeeded(void)
count++; count++;
WRITEUINT32(p, wadfiles[i]->filesize); WRITEUINT32(p, wadfiles[i]->filesize);
nameonly(strcpy(wadfilename, wadfiles[i]->filename));
WRITESTRINGN(p, wadfilename, MAX_WADPATH); WRITESTRINGN(p, wadfilename, MAX_WADPATH);
WRITEMEM(p, wadfiles[i]->md5sum, 16); WRITEMEM(p, wadfiles[i]->md5sum, 16);
} }
netbuffer->u.serverinfo.fileneedednum = (UINT8)count;
if (netbuffer->packettype == PT_MOREFILESNEEDED)
netbuffer->u.filesneededcfg.num = count;
else
netbuffer->u.serverinfo.fileneedednum = count;
return p; return p;
} }
void AllocFileNeeded(INT32 size)
{
if (fileneeded == NULL)
fileneeded = Z_Calloc(sizeof(fileneeded_t) * size, PU_STATIC, NULL);
else
fileneeded = Z_Realloc(fileneeded, sizeof(fileneeded_t) * size, PU_STATIC, NULL);
}
void FreeFileNeeded(void)
{
Z_Free(fileneeded);
fileneeded = NULL;
}
/** Parses the serverinfo packet and fills the fileneeded table on client /** Parses the serverinfo packet and fills the fileneeded table on client
* *
* \param fileneedednum_parm The number of files needed to join the server * \param fileneedednum_parm The number of files needed to join the server
* \param fileneededstr The memory block containing the list of needed files * \param fileneededstr The memory block containing the list of needed files
* *
*/ */
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr) void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile)
{ {
INT32 i; INT32 i;
UINT8 *p; UINT8 *p;
UINT8 filestatus; UINT8 filestatus;
fileneedednum = fileneedednum_parm; fileneedednum = firstfile + fileneedednum_parm;
p = (UINT8 *)fileneededstr; p = (UINT8 *)fileneededstr;
for (i = 0; i < fileneedednum; i++)
AllocFileNeeded(fileneedednum);
for (i = firstfile; i < fileneedednum; i++)
{ {
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet fileneeded[i].type = FILENEEDED_WAD;
fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet
fileneeded[i].justdownloaded = false; fileneeded[i].justdownloaded = false;
filestatus = READUINT8(p); // The first byte is the file status filestatus = READUINT8(p); // The first byte is the file status
fileneeded[i].folder = READUINT8(p); // The second byte is the folder flag fileneeded[i].folder = READUINT8(p); // The second byte is the folder flag
@ -191,7 +253,11 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
lastfilenum = -1; lastfilenum = -1;
#endif #endif
FreeFileNeeded();
AllocFileNeeded(1);
fileneedednum = 1; fileneedednum = 1;
fileneeded[0].type = FILENEEDED_SAVEGAME;
fileneeded[0].status = FS_REQUESTED; fileneeded[0].status = FS_REQUESTED;
fileneeded[0].justdownloaded = false; fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX; fileneeded[0].totalsize = UINT32_MAX;
@ -322,14 +388,18 @@ boolean CL_SendFileRequest(void)
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)) if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD))
{ {
totalfreespaceneeded += fileneeded[i].totalsize; totalfreespaceneeded += fileneeded[i].totalsize;
nameonly(fileneeded[i].filename);
WRITEUINT8(p, i); // fileid WRITEUINT8(p, i); // fileid
WRITESTRINGN(p, fileneeded[i].filename, MAX_WADPATH);
// put it in download dir // put it in download dir
nameonly(fileneeded[i].filename);
strcatbf(fileneeded[i].filename, downloaddir, "/"); strcatbf(fileneeded[i].filename, downloaddir, "/");
fileneeded[i].status = FS_REQUESTED; fileneeded[i].status = FS_REQUESTED;
} }
WRITEUINT8(p, 0xFF); WRITEUINT8(p, 0xFF);
I_GetDiskFreeSpace(&availablefreespace); I_GetDiskFreeSpace(&availablefreespace);
if (totalfreespaceneeded > availablefreespace) if (totalfreespaceneeded > availablefreespace)
I_Error("To play on this server you must download %s KB,\n" I_Error("To play on this server you must download %s KB,\n"
@ -345,21 +415,22 @@ boolean CL_SendFileRequest(void)
// returns false if a requested file was not found or cannot be sent // returns false if a requested file was not found or cannot be sent
boolean PT_RequestFile(INT32 node) boolean PT_RequestFile(INT32 node)
{ {
char wad[MAX_WADPATH+1];
UINT8 *p = netbuffer->u.textcmd; UINT8 *p = netbuffer->u.textcmd;
UINT8 id; UINT8 id;
while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow
{ {
id = READUINT8(p); id = READUINT8(p);
if (id == 0xFF) if (id == 0xFF)
break; break;
READSTRINGN(p, wad, MAX_WADPATH);
if (!AddFileToSendQueue(node, wad, id)) if (!AddFileToSendQueue(node, id))
{ {
SV_AbortSendFiles(node); SV_AbortSendFiles(node);
return false; // don't read the rest of the files return false; // don't read the rest of the files
} }
} }
return true; // no problems with any files return true; // no problems with any files
} }
@ -368,23 +439,16 @@ boolean PT_RequestFile(INT32 node)
* \return 0 if some files are missing * \return 0 if some files are missing
* 1 if all files exist * 1 if all files exist
* 2 if some already loaded files are not requested or are in a different order * 2 if some already loaded files are not requested or are in a different order
* 3 too many files, over WADLIMIT
* 4 still checking, continuing next tic
* *
*/ */
INT32 CL_CheckFiles(void) INT32 CL_CheckFiles(void)
{ {
INT32 i, j; INT32 i, j;
char wadfilename[MAX_WADPATH]; char wadfilename[MAX_WADPATH];
INT32 ret = 1; size_t filestoload = 0;
size_t packetsize = 0; boolean downloadrequired = false;
size_t filestoget = 0;
// if (M_CheckParm("-nofiles"))
// return 1;
// the first is the iwad (the main wad file)
// we don't care if it's called srb2.pk3 or not.
// Never download the IWAD, just assume it's there and identical
fileneeded[0].status = FS_OPEN;
// Modified game handling -- check for an identical file list // Modified game handling -- check for an identical file list
// must be identical in files loaded AND in order // must be identical in files loaded AND in order
@ -392,7 +456,7 @@ INT32 CL_CheckFiles(void)
if (modifiedgame) if (modifiedgame)
{ {
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n"); CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;) for (i = 0, j = mainwads; i < fileneedednum || j < numwadfiles;)
{ {
if (j < numwadfiles && !wadfiles[j]->important) if (j < numwadfiles && !wadfiles[j]->important)
{ {
@ -419,15 +483,21 @@ INT32 CL_CheckFiles(void)
return 1; return 1;
} }
// See W_InitFile in w_wad.c for (i = 0; i < fileneedednum; i++)
packetsize = packetsizetally;
for (i = 1; i < fileneedednum; i++)
{ {
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
downloadrequired = true;
if (fileneeded[i].status != FS_OPEN)
filestoload++;
if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics
continue;
CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
// Check in already loaded files // Check in already loaded files
for (j = 1; wadfiles[j]; j++) for (j = mainwads; wadfiles[j]; j++)
{ {
nameonly(strcpy(wadfilename, wadfiles[j]->filename)); nameonly(strcpy(wadfilename, wadfiles[j]->filename));
if (!stricmp(wadfilename, fileneeded[i].filename) && if (!stricmp(wadfilename, fileneeded[i].filename) &&
@ -435,43 +505,34 @@ INT32 CL_CheckFiles(void)
{ {
CONS_Debug(DBG_NETPLAY, "already loaded\n"); CONS_Debug(DBG_NETPLAY, "already loaded\n");
fileneeded[i].status = FS_OPEN; fileneeded[i].status = FS_OPEN;
break; return 4;
} }
} }
if (fileneeded[i].status != FS_NOTFOUND)
continue;
if (fileneeded[i].folder)
packetsize += strlen(fileneeded[i].filename) + FILENEEDEDSIZE;
else
packetsize += nameonlylength(fileneeded[i].filename) + FILENEEDEDSIZE;
if ((numwadfiles+filestoget >= MAX_WADFILES)
|| (packetsize > MAXFILENEEDED*sizeof(UINT8)))
return 3;
filestoget++;
if (fileneeded[i].folder) if (fileneeded[i].folder)
fileneeded[i].status = findfolder(fileneeded[i].filename); fileneeded[i].status = findfolder(fileneeded[i].filename);
else else
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true); fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status); CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
if (fileneeded[i].status != FS_FOUND) return 4;
ret = 0;
} }
return ret;
//now making it here means we've checked the entire list and no FS_NOTCHECKED files remain
if (numwadfiles+filestoload > MAX_WADFILES)
return 3;
else if (downloadrequired)
return 0; //some stuff is FS_NOTFOUND, needs download
else
return 1; //everything is FS_OPEN or FS_FOUND, proceed to loading
} }
// Load it now // Load it now
void CL_LoadServerFiles(void) boolean CL_LoadServerFiles(void)
{ {
INT32 i; INT32 i;
// if (M_CheckParm("-nofiles")) for (i = 0; i < fileneedednum; i++)
// return;
for (i = 1; i < fileneedednum; i++)
{ {
if (fileneeded[i].status == FS_OPEN) if (fileneeded[i].status == FS_OPEN)
continue; // Already loaded continue; // Already loaded
@ -483,6 +544,7 @@ void CL_LoadServerFiles(void)
P_AddWadFile(fileneeded[i].filename); P_AddWadFile(fileneeded[i].filename);
G_SetGameModified(true); G_SetGameModified(true);
fileneeded[i].status = FS_OPEN; fileneeded[i].status = FS_OPEN;
return false;
} }
else if (fileneeded[i].status == FS_MD5SUMBAD) else if (fileneeded[i].status == FS_MD5SUMBAD)
I_Error("Wrong version of file %s", fileneeded[i].filename); I_Error("Wrong version of file %s", fileneeded[i].filename);
@ -508,6 +570,7 @@ void CL_LoadServerFiles(void)
fileneeded[i].status, s); fileneeded[i].status, s);
} }
} }
return true;
} }
void AddLuaFileTransfer(const char *filename, const char *mode) void AddLuaFileTransfer(const char *filename, const char *mode)
@ -689,7 +752,11 @@ void CL_PrepareDownloadLuaFile(void)
netbuffer->packettype = PT_ASKLUAFILE; netbuffer->packettype = PT_ASKLUAFILE;
HSendPacket(servernode, true, 0, 0); HSendPacket(servernode, true, 0, 0);
FreeFileNeeded();
AllocFileNeeded(1);
fileneedednum = 1; fileneedednum = 1;
fileneeded[0].type = FILENEEDED_LUAFILE;
fileneeded[0].status = FS_REQUESTED; fileneeded[0].status = FS_REQUESTED;
fileneeded[0].justdownloaded = false; fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX; fileneeded[0].totalsize = UINT32_MAX;
@ -716,15 +783,11 @@ static INT32 filestosend = 0;
* \sa AddLuaFileToSendQueue * \sa AddLuaFileToSendQueue
* *
*/ */
static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid) static boolean AddFileToSendQueue(INT32 node, UINT8 fileid)
{ {
filetx_t **q; // A pointer to the "next" field of the last file in the list filetx_t **q; // A pointer to the "next" field of the last file in the list
filetx_t *p; // The new file request filetx_t *p; // The new file request
INT32 i; UINT16 wadnum;
char wadfilename[MAX_WADPATH];
if (cv_noticedownload.value)
CONS_Printf("Sending file \"%s\" to node %d (%s)\n", filename, node, I_GetNodeAddress(node));
// Find the last file in the list and set a pointer to its "next" field // Find the last file in the list and set a pointer to its "next" field
q = &transfer[node].txlist; q = &transfer[node].txlist;
@ -744,51 +807,43 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid
if (!p->id.filename) if (!p->id.filename)
I_Error("AddFileToSendQueue: No more memory\n"); I_Error("AddFileToSendQueue: No more memory\n");
// Set the file name and get rid of the path // Find the wad the ID refers to
strlcpy(p->id.filename, filename, MAX_WADPATH); wadnum = GetWadNumFromFileNeededId(fileid);
nameonly(p->id.filename);
// Look for the requested file through all loaded files
for (i = 0; wadfiles[i]; i++)
{
strlcpy(wadfilename, wadfiles[i]->filename, MAX_WADPATH);
nameonly(wadfilename);
if (!stricmp(wadfilename, p->id.filename))
{
// Copy file name with full path
strlcpy(p->id.filename, wadfiles[i]->filename, MAX_WADPATH);
break;
}
}
// Handle non-loaded file requests // Handle non-loaded file requests
if (!wadfiles[i]) if (wadnum == UINT16_MAX)
{ {
DEBFILE(va("%s not found in wadfiles\n", filename)); DEBFILE(va("fileneeded %d not found in wadfiles\n", fileid));
// This formerly checked if (!findfile(p->id.filename, NULL, true)) // This formerly checked if (!findfile(p->id.filename, NULL, true))
// Not found // Not found
// Don't inform client // Don't inform client
DEBFILE(va("Client %d request %s: not found\n", node, filename)); DEBFILE(va("Client %d request fileneeded %d: not found\n", node, fileid));
free(p->id.filename); free(p->id.filename);
free(p); free(p);
*q = NULL; *q = NULL;
return false; // cancel the rest of the requests return false; // cancel the rest of the requests
} }
// Set the file name and get rid of the path
strlcpy(p->id.filename, wadfiles[wadnum]->filename, MAX_WADPATH);
// Handle huge file requests (i.e. bigger than cv_maxsend.value KB) // Handle huge file requests (i.e. bigger than cv_maxsend.value KB)
if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024) if (wadfiles[wadnum]->filesize > (UINT32)cv_maxsend.value * 1024)
{ {
// Too big // Too big
// Don't inform client (client sucks, man) // Don't inform client (client sucks, man)
DEBFILE(va("Client %d request %s: file too big, not sending\n", node, filename)); DEBFILE(va("Client %d request %s: file too big, not sending\n", node, p->id.filename));
free(p->id.filename); free(p->id.filename);
free(p); free(p);
*q = NULL; *q = NULL;
return false; // cancel the rest of the requests return false; // cancel the rest of the requests
} }
DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node)); if (cv_noticedownload.value)
CONS_Printf("Sending file \"%s\" to node %d (%s)\n", p->id.filename, node, I_GetNodeAddress(node));
DEBFILE(va("Sending file %s (id=%d) to %d\n", p->id.filename, fileid, node));
p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it
p->fileid = fileid; p->fileid = fileid;
p->next = NULL; // End of list p->next = NULL; // End of list
@ -925,7 +980,6 @@ static void SV_EndFileSend(INT32 node)
filestosend--; filestosend--;
} }
#define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH)
#define FILEFRAGMENTSIZE (software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE)) #define FILEFRAGMENTSIZE (software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE))
/** Handles file transmission /** Handles file transmission
@ -958,14 +1012,7 @@ void FileSendTicker(void)
if (!filestosend) // No file to send if (!filestosend) // No file to send
return; return;
if (cv_downloadspeed.value) // New behavior packetsent = cv_downloadspeed.value;
packetsent = cv_downloadspeed.value;
else // Old behavior
{
packetsent = PACKETPERTIC;
if (!packetsent)
packetsent = 1;
}
netbuffer->packettype = PT_FILEFRAGMENT; netbuffer->packettype = PT_FILEFRAGMENT;
@ -1242,6 +1289,9 @@ void PT_FileFragment(void)
UINT16 boundedfragmentsize = doomcom->datalength - BASEPACKETSIZE - sizeof(netbuffer->u.filetxpak); UINT16 boundedfragmentsize = doomcom->datalength - BASEPACKETSIZE - sizeof(netbuffer->u.filetxpak);
char *filename; char *filename;
if (!file)
return;
filename = va("%s", file->filename); filename = va("%s", file->filename);
nameonly(filename); nameonly(filename);
@ -1353,6 +1403,7 @@ void PT_FileFragment(void)
// Tell the server we have received the file // Tell the server we have received the file
netbuffer->packettype = PT_HASLUAFILE; netbuffer->packettype = PT_HASLUAFILE;
HSendPacket(servernode, true, 0, 0); HSendPacket(servernode, true, 0, 0);
FreeFileNeeded();
} }
} }
} }
@ -1423,32 +1474,37 @@ void CloseNetFile(void)
SV_AbortSendFiles(i); SV_AbortSendFiles(i);
// Receiving a file? // Receiving a file?
for (i = 0; i < MAX_WADFILES; i++) if (fileneeded)
if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file) {
{ for (i = 0; i < fileneedednum; i++)
fclose(fileneeded[i].file); if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
free(fileneeded[i].ackpacket);
if (!pauseddownload && i != 0) // 0 is either srb2.srb or the gamestate...
{ {
// Don't remove the file, save it for later in case we resume the download fclose(fileneeded[i].file);
pauseddownload = malloc(sizeof(*pauseddownload)); free(fileneeded[i].ackpacket);
if (!pauseddownload)
I_Error("CloseNetFile: No more memory\n");
strcpy(pauseddownload->filename, fileneeded[i].filename); if (!pauseddownload && (fileneeded[i].type == FILENEEDED_WAD || i != 0)) // 0 is the gamestate...
memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16); {
pauseddownload->currentsize = fileneeded[i].currentsize; // Don't remove the file, save it for later in case we resume the download
pauseddownload->receivedfragments = fileneeded[i].receivedfragments; pauseddownload = malloc(sizeof(*pauseddownload));
pauseddownload->fragmentsize = fileneeded[i].fragmentsize; if (!pauseddownload)
I_Error("CloseNetFile: No more memory\n");
strcpy(pauseddownload->filename, fileneeded[i].filename);
memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16);
pauseddownload->currentsize = fileneeded[i].currentsize;
pauseddownload->receivedfragments = fileneeded[i].receivedfragments;
pauseddownload->fragmentsize = fileneeded[i].fragmentsize;
}
else
{
// File is not complete, delete it.
free(fileneeded[i].receivedfragments);
remove(fileneeded[i].filename);
}
} }
else }
{
free(fileneeded[i].receivedfragments); FreeFileNeeded();
// File is not complete delete it
remove(fileneeded[i].filename);
}
}
} }
void Command_Downloads_f(void) void Command_Downloads_f(void)

View file

@ -27,6 +27,7 @@ typedef enum
typedef enum typedef enum
{ {
FS_NOTCHECKED,
FS_NOTFOUND, FS_NOTFOUND,
FS_FOUND, FS_FOUND,
FS_REQUESTED, FS_REQUESTED,
@ -35,13 +36,21 @@ typedef enum
FS_MD5SUMBAD FS_MD5SUMBAD
} filestatus_t; } filestatus_t;
typedef enum
{
FILENEEDED_WAD,
FILENEEDED_SAVEGAME,
FILENEEDED_LUAFILE
} fileneededtype_t;
typedef struct typedef struct
{ {
UINT8 willsend; // Is the server willing to send it?
UINT8 folder; // File is a folder
char filename[MAX_WADPATH]; char filename[MAX_WADPATH];
UINT8 md5sum[16]; UINT8 md5sum[16];
filestatus_t status; // The value returned by recsearch filestatus_t status; // The value returned by recsearch
UINT8 willsend; // Is the server willing to send it?
UINT8 folder; // File is a folder
fileneededtype_t type;
boolean justdownloaded; // To prevent late fragments from causing an I_Error boolean justdownloaded; // To prevent late fragments from causing an I_Error
// Used only for download // Used only for download
@ -58,19 +67,25 @@ typedef struct
#define FILENEEDEDSIZE 23 #define FILENEEDEDSIZE 23
extern INT32 fileneedednum; extern INT32 fileneedednum;
extern fileneeded_t fileneeded[MAX_WADFILES]; extern fileneeded_t *fileneeded;
extern char downloaddir[512]; extern char downloaddir[512];
#ifndef NONET #ifndef NONET
extern INT32 lastfilenum; extern INT32 lastfilenum;
extern INT32 downloadcompletednum;
extern UINT32 downloadcompletedsize;
extern INT32 totalfilesrequestednum;
extern UINT32 totalfilesrequestedsize;
#endif #endif
UINT8 *PutFileNeeded(void); void AllocFileNeeded(INT32 size);
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr); void FreeFileNeeded(void);
UINT8 *PutFileNeeded(UINT16 firstfile);
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile);
void CL_PrepareDownloadSaveGame(const char *tmpsave); void CL_PrepareDownloadSaveGame(const char *tmpsave);
INT32 CL_CheckFiles(void); INT32 CL_CheckFiles(void);
void CL_LoadServerFiles(void); boolean CL_LoadServerFiles(void);
void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemethod, void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemethod,
UINT8 fileid); UINT8 fileid);

View file

@ -5226,6 +5226,7 @@ struct int_const_s const INT_CONST[] = {
{"FF_CRUMBLE",FF_CRUMBLE}, ///< Falls 2 seconds after being stepped on, and randomly brings all touching crumbling 3dfloors down with it, providing their master sectors share the same tag (allows crumble platforms above or below, to also exist). {"FF_CRUMBLE",FF_CRUMBLE}, ///< Falls 2 seconds after being stepped on, and randomly brings all touching crumbling 3dfloors down with it, providing their master sectors share the same tag (allows crumble platforms above or below, to also exist).
{"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
{"FF_MARIO",FF_MARIO}, ///< Acts like a question block when hit from underneath. Goodie spawned at top is determined by master sector. {"FF_MARIO",FF_MARIO}, ///< Acts like a question block when hit from underneath. Goodie spawned at top is determined by master sector.
{"FF_BUSTUP",FF_BUSTUP}, ///< You can spin through/punch this block and it will crumble!
{"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand! {"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand!
{"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top. {"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top.
{"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity. {"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity.
@ -5236,12 +5237,10 @@ struct int_const_s const INT_CONST[] = {
{"FF_BOUNCY",FF_BOUNCY}, ///< Bounces players {"FF_BOUNCY",FF_BOUNCY}, ///< Bounces players
{"FF_SPLAT",FF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible) {"FF_SPLAT",FF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible)
// FOF special flags // FOF bustable flags
{"FS_PUSHABLES",FS_PUSHABLES}, {"FB_PUSHABLES",FB_PUSHABLES},
{"FS_EXECUTOR",FS_EXECUTOR}, {"FB_EXECUTOR",FB_EXECUTOR},
{"FS_ONLYBOTTOM",FS_ONLYBOTTOM}, {"FB_ONLYBOTTOM",FB_ONLYBOTTOM},
{"FS_BUSTMASK",FS_BUSTMASK},
{"FS_DAMPEN",FS_DAMPEN},
// Bustable FOF type // Bustable FOF type
{"BT_TOUCH",BT_TOUCH}, {"BT_TOUCH",BT_TOUCH},

View file

@ -152,6 +152,9 @@ extern char logfilename[1024];
// Comment or uncomment this as necessary. // Comment or uncomment this as necessary.
#define USE_PATCH_DTA #define USE_PATCH_DTA
// Enforce a limit of loaded WAD files.
//#define ENFORCE_WAD_LIMIT
// Use .kart extension addons // Use .kart extension addons
//#define USE_KART //#define USE_KART

View file

@ -1091,11 +1091,11 @@ static const char *credits[] = {
"Kepa \"Nev3r\" Iceta", "Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe", "Thomas \"Shadow Hog\" Igoe",
"Iestyn \"Monster Iestyn\" Jealous", "Iestyn \"Monster Iestyn\" Jealous",
"\"Jimita\"",
"\"Kaito Sinclaire\"", "\"Kaito Sinclaire\"",
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"Ronald \"Furyhunter\" Kinard", // The SDL2 port "Ronald \"Furyhunter\" Kinard", // The SDL2 port
"\"Lat'\"", // SRB2-CHAT, the chat window from Kart "\"Lat'\"", // SRB2-CHAT, the chat window from Kart
"\"LZA\"",
"Matthew \"Shuffle\" Marsalko", "Matthew \"Shuffle\" Marsalko",
"Steven \"StroggOnMeth\" McGranahan", "Steven \"StroggOnMeth\" McGranahan",
"\"Morph\"", // For SRB2Morphed stuff "\"Morph\"", // For SRB2Morphed stuff
@ -1167,8 +1167,8 @@ static const char *credits[] = {
"Alexander \"DrTapeworm\" Moench-Ford", "Alexander \"DrTapeworm\" Moench-Ford",
"Stefan \"Stuf\" Rimalia", "Stefan \"Stuf\" Rimalia",
"Shane Mychal Sexton", "Shane Mychal Sexton",
"David \"Big Wave Dave\" Spencer Sr.", "Dave \"Big Wave Dave\" Spencer",
"David \"Instant Sonic\" Spencer Jr.", "David \"instantSonic\" Spencer",
"\"SSNTails\"", "\"SSNTails\"",
"", "",
"\1Level Design", "\1Level Design",
@ -1219,7 +1219,7 @@ static const char *credits[] = {
"Bill \"Tets\" Reed", "Bill \"Tets\" Reed",
"", "",
"\1Special Thanks", "\1Special Thanks",
"iD Software", "id Software",
"Doom Legacy Project", "Doom Legacy Project",
"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak "FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
"Kart Krew", "Kart Krew",

View file

@ -338,9 +338,6 @@ size_t dir_on[menudepth];
UINT8 refreshdirmenu = 0; UINT8 refreshdirmenu = 0;
char *refreshdirname = NULL; char *refreshdirname = NULL;
size_t packetsizetally = 0;
size_t mainwadstally = 0;
#define dirpathlen 1024 #define dirpathlen 1024
#define maxdirdepth 48 #define maxdirdepth 48
@ -830,7 +827,7 @@ char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) pl
#endif #endif
"\5.pk3", "\5.soc", "\5.lua"}; // addfile "\5.pk3", "\5.soc", "\5.lua"}; // addfile
char filenamebuf[MAX_WADFILES][MAX_WADPATH]; static char (*filenamebuf)[MAX_WADPATH];
static boolean filemenucmp(char *haystack, char *needle) static boolean filemenucmp(char *haystack, char *needle)
{ {
@ -1102,6 +1099,10 @@ boolean preparefilemenu(boolean samedepth)
if (ext >= EXT_LOADSTART) if (ext >= EXT_LOADSTART)
{ {
size_t i; size_t i;
if (filenamebuf == NULL)
filenamebuf = calloc(sizeof(char) * MAX_WADPATH, numwadfiles);
for (i = 0; i < numwadfiles; i++) for (i = 0; i < numwadfiles; i++)
{ {
if (!filenamebuf[i][0]) if (!filenamebuf[i][0])
@ -1151,6 +1152,12 @@ boolean preparefilemenu(boolean samedepth)
} }
} }
if (filenamebuf)
{
free(filenamebuf);
filenamebuf = NULL;
}
closedir(dirhandle); closedir(dirhandle);
if ((menudepthleft != menudepth-1) // now for UP... entry if ((menudepthleft != menudepth-1) // now for UP... entry

View file

@ -53,9 +53,6 @@ extern size_t dir_on[menudepth];
extern UINT8 refreshdirmenu; extern UINT8 refreshdirmenu;
extern char *refreshdirname; extern char *refreshdirname;
extern size_t packetsizetally;
extern size_t mainwadstally;
typedef enum typedef enum
{ {
EXT_FOLDER = 0, EXT_FOLDER = 0,

View file

@ -2433,12 +2433,13 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
{ {
WRITEUINT8(demo_p, (kill) ? METALDEATH : DEMOMARKER); // add the demo end (or metal death) marker WRITEUINT8(demo_p, (kill) ? METALDEATH : DEMOMARKER); // add the demo end (or metal death) marker
WriteDemoChecksum(); WriteDemoChecksum();
saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file. sprintf(demoname, "%sMS.LMP", G_BuildMapName(gamemap));
saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
} }
free(demobuffer); free(demobuffer);
metalrecording = false; metalrecording = false;
if (saved) if (saved)
I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap)); I_Error("Saved to %s", demoname);
I_Error("Failed to save demo!"); I_Error("Failed to save demo!");
} }

View file

@ -1549,8 +1549,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// Note: Majority of botstuffs are handled in G_Ticker now. // Note: Majority of botstuffs are handled in G_Ticker now.
if (player->bot == BOT_2PHUMAN) //Player-controlled bot if (player->bot == BOT_2PHUMAN) //Player-controlled bot
{ {
G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); // empty, or external driver // Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Strafe
// Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Legacy
cmd->angleturn = (INT16)((localangle - *myangle) >> 16); cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
} }

View file

@ -233,323 +233,323 @@ typedef struct
static keyname_t keynames[] = static keyname_t keynames[] =
{ {
{KEY_SPACE, "SPACE"}, {KEY_SPACE, "space"},
{KEY_CAPSLOCK, "CAPS LOCK"}, {KEY_CAPSLOCK, "caps lock"},
{KEY_ENTER, "ENTER"}, {KEY_ENTER, "enter"},
{KEY_TAB, "TAB"}, {KEY_TAB, "tab"},
{KEY_ESCAPE, "ESCAPE"}, {KEY_ESCAPE, "escape"},
{KEY_BACKSPACE, "BACKSPACE"}, {KEY_BACKSPACE, "backspace"},
{KEY_NUMLOCK, "NUMLOCK"}, {KEY_NUMLOCK, "numlock"},
{KEY_SCROLLLOCK, "SCROLLLOCK"}, {KEY_SCROLLLOCK, "scrolllock"},
// bill gates keys // bill gates keys
{KEY_LEFTWIN, "LEFTWIN"}, {KEY_LEFTWIN, "leftwin"},
{KEY_RIGHTWIN, "RIGHTWIN"}, {KEY_RIGHTWIN, "rightwin"},
{KEY_MENU, "MENU"}, {KEY_MENU, "menu"},
{KEY_LSHIFT, "LSHIFT"}, {KEY_LSHIFT, "lshift"},
{KEY_RSHIFT, "RSHIFT"}, {KEY_RSHIFT, "rshift"},
{KEY_LSHIFT, "SHIFT"}, {KEY_LSHIFT, "shift"},
{KEY_LCTRL, "LCTRL"}, {KEY_LCTRL, "lctrl"},
{KEY_RCTRL, "RCTRL"}, {KEY_RCTRL, "rctrl"},
{KEY_LCTRL, "CTRL"}, {KEY_LCTRL, "ctrl"},
{KEY_LALT, "LALT"}, {KEY_LALT, "lalt"},
{KEY_RALT, "RALT"}, {KEY_RALT, "ralt"},
{KEY_LALT, "ALT"}, {KEY_LALT, "alt"},
// keypad keys // keypad keys
{KEY_KPADSLASH, "KEYPAD /"}, {KEY_KPADSLASH, "keypad /"},
{KEY_KEYPAD7, "KEYPAD 7"}, {KEY_KEYPAD7, "keypad 7"},
{KEY_KEYPAD8, "KEYPAD 8"}, {KEY_KEYPAD8, "keypad 8"},
{KEY_KEYPAD9, "KEYPAD 9"}, {KEY_KEYPAD9, "keypad 9"},
{KEY_MINUSPAD, "KEYPAD -"}, {KEY_MINUSPAD, "keypad -"},
{KEY_KEYPAD4, "KEYPAD 4"}, {KEY_KEYPAD4, "keypad 4"},
{KEY_KEYPAD5, "KEYPAD 5"}, {KEY_KEYPAD5, "keypad 5"},
{KEY_KEYPAD6, "KEYPAD 6"}, {KEY_KEYPAD6, "keypad 6"},
{KEY_PLUSPAD, "KEYPAD +"}, {KEY_PLUSPAD, "keypad +"},
{KEY_KEYPAD1, "KEYPAD 1"}, {KEY_KEYPAD1, "keypad 1"},
{KEY_KEYPAD2, "KEYPAD 2"}, {KEY_KEYPAD2, "keypad 2"},
{KEY_KEYPAD3, "KEYPAD 3"}, {KEY_KEYPAD3, "keypad 3"},
{KEY_KEYPAD0, "KEYPAD 0"}, {KEY_KEYPAD0, "keypad 0"},
{KEY_KPADDEL, "KEYPAD ."}, {KEY_KPADDEL, "keypad ."},
// extended keys (not keypad) // extended keys (not keypad)
{KEY_HOME, "HOME"}, {KEY_HOME, "home"},
{KEY_UPARROW, "UP ARROW"}, {KEY_UPARROW, "up arrow"},
{KEY_PGUP, "PGUP"}, {KEY_PGUP, "pgup"},
{KEY_LEFTARROW, "LEFT ARROW"}, {KEY_LEFTARROW, "left arrow"},
{KEY_RIGHTARROW, "RIGHT ARROW"}, {KEY_RIGHTARROW, "right arrow"},
{KEY_END, "END"}, {KEY_END, "end"},
{KEY_DOWNARROW, "DOWN ARROW"}, {KEY_DOWNARROW, "down arrow"},
{KEY_PGDN, "PGDN"}, {KEY_PGDN, "pgdn"},
{KEY_INS, "INS"}, {KEY_INS, "ins"},
{KEY_DEL, "DEL"}, {KEY_DEL, "del"},
// other keys // other keys
{KEY_F1, "F1"}, {KEY_F1, "f1"},
{KEY_F2, "F2"}, {KEY_F2, "f2"},
{KEY_F3, "F3"}, {KEY_F3, "f3"},
{KEY_F4, "F4"}, {KEY_F4, "f4"},
{KEY_F5, "F5"}, {KEY_F5, "f5"},
{KEY_F6, "F6"}, {KEY_F6, "f6"},
{KEY_F7, "F7"}, {KEY_F7, "f7"},
{KEY_F8, "F8"}, {KEY_F8, "f8"},
{KEY_F9, "F9"}, {KEY_F9, "f9"},
{KEY_F10, "F10"}, {KEY_F10, "f10"},
{KEY_F11, "F11"}, {KEY_F11, "f11"},
{KEY_F12, "F12"}, {KEY_F12, "f12"},
// KEY_CONSOLE has an exception in the keyname code // KEY_CONSOLE has an exception in the keyname code
{'`', "TILDE"}, {'`', "TILDE"},
{KEY_PAUSE, "PAUSE/BREAK"}, {KEY_PAUSE, "pause/break"},
// virtual keys for mouse buttons and joystick buttons // virtual keys for mouse buttons and joystick buttons
{KEY_MOUSE1+0,"MOUSE1"}, {KEY_MOUSE1+0,"mouse1"},
{KEY_MOUSE1+1,"MOUSE2"}, {KEY_MOUSE1+1,"mouse2"},
{KEY_MOUSE1+2,"MOUSE3"}, {KEY_MOUSE1+2,"mouse3"},
{KEY_MOUSE1+3,"MOUSE4"}, {KEY_MOUSE1+3,"mouse4"},
{KEY_MOUSE1+4,"MOUSE5"}, {KEY_MOUSE1+4,"mouse5"},
{KEY_MOUSE1+5,"MOUSE6"}, {KEY_MOUSE1+5,"mouse6"},
{KEY_MOUSE1+6,"MOUSE7"}, {KEY_MOUSE1+6,"mouse7"},
{KEY_MOUSE1+7,"MOUSE8"}, {KEY_MOUSE1+7,"mouse8"},
{KEY_2MOUSE1+0,"SEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2 {KEY_2MOUSE1+0,"sec_mouse2"}, // BP: sorry my mouse handler swap button 1 and 2
{KEY_2MOUSE1+1,"SEC_MOUSE1"}, {KEY_2MOUSE1+1,"sec_mouse1"},
{KEY_2MOUSE1+2,"SEC_MOUSE3"}, {KEY_2MOUSE1+2,"sec_mouse3"},
{KEY_2MOUSE1+3,"SEC_MOUSE4"}, {KEY_2MOUSE1+3,"sec_mouse4"},
{KEY_2MOUSE1+4,"SEC_MOUSE5"}, {KEY_2MOUSE1+4,"sec_mouse5"},
{KEY_2MOUSE1+5,"SEC_MOUSE6"}, {KEY_2MOUSE1+5,"sec_mouse6"},
{KEY_2MOUSE1+6,"SEC_MOUSE7"}, {KEY_2MOUSE1+6,"sec_mouse7"},
{KEY_2MOUSE1+7,"SEC_MOUSE8"}, {KEY_2MOUSE1+7,"sec_mouse8"},
{KEY_MOUSEWHEELUP, "Wheel 1 UP"}, {KEY_MOUSEWHEELUP, "wheel 1 up"},
{KEY_MOUSEWHEELDOWN, "Wheel 1 Down"}, {KEY_MOUSEWHEELDOWN, "wheel 1 down"},
{KEY_2MOUSEWHEELUP, "Wheel 2 UP"}, {KEY_2MOUSEWHEELUP, "wheel 2 up"},
{KEY_2MOUSEWHEELDOWN, "Wheel 2 Down"}, {KEY_2MOUSEWHEELDOWN, "wheel 2 down"},
{KEY_JOY1+0, "JOY1"}, {KEY_JOY1+0, "joy1"},
{KEY_JOY1+1, "JOY2"}, {KEY_JOY1+1, "joy2"},
{KEY_JOY1+2, "JOY3"}, {KEY_JOY1+2, "joy3"},
{KEY_JOY1+3, "JOY4"}, {KEY_JOY1+3, "joy4"},
{KEY_JOY1+4, "JOY5"}, {KEY_JOY1+4, "joy5"},
{KEY_JOY1+5, "JOY6"}, {KEY_JOY1+5, "joy6"},
{KEY_JOY1+6, "JOY7"}, {KEY_JOY1+6, "joy7"},
{KEY_JOY1+7, "JOY8"}, {KEY_JOY1+7, "joy8"},
{KEY_JOY1+8, "JOY9"}, {KEY_JOY1+8, "joy9"},
#if !defined (NOMOREJOYBTN_1S) #if !defined (NOMOREJOYBTN_1S)
// we use up to 32 buttons in DirectInput // we use up to 32 buttons in DirectInput
{KEY_JOY1+9, "JOY10"}, {KEY_JOY1+9, "joy10"},
{KEY_JOY1+10, "JOY11"}, {KEY_JOY1+10, "joy11"},
{KEY_JOY1+11, "JOY12"}, {KEY_JOY1+11, "joy12"},
{KEY_JOY1+12, "JOY13"}, {KEY_JOY1+12, "joy13"},
{KEY_JOY1+13, "JOY14"}, {KEY_JOY1+13, "joy14"},
{KEY_JOY1+14, "JOY15"}, {KEY_JOY1+14, "joy15"},
{KEY_JOY1+15, "JOY16"}, {KEY_JOY1+15, "joy16"},
{KEY_JOY1+16, "JOY17"}, {KEY_JOY1+16, "joy17"},
{KEY_JOY1+17, "JOY18"}, {KEY_JOY1+17, "joy18"},
{KEY_JOY1+18, "JOY19"}, {KEY_JOY1+18, "joy19"},
{KEY_JOY1+19, "JOY20"}, {KEY_JOY1+19, "joy20"},
{KEY_JOY1+20, "JOY21"}, {KEY_JOY1+20, "joy21"},
{KEY_JOY1+21, "JOY22"}, {KEY_JOY1+21, "joy22"},
{KEY_JOY1+22, "JOY23"}, {KEY_JOY1+22, "joy23"},
{KEY_JOY1+23, "JOY24"}, {KEY_JOY1+23, "joy24"},
{KEY_JOY1+24, "JOY25"}, {KEY_JOY1+24, "joy25"},
{KEY_JOY1+25, "JOY26"}, {KEY_JOY1+25, "joy26"},
{KEY_JOY1+26, "JOY27"}, {KEY_JOY1+26, "joy27"},
{KEY_JOY1+27, "JOY28"}, {KEY_JOY1+27, "joy28"},
{KEY_JOY1+28, "JOY29"}, {KEY_JOY1+28, "joy29"},
{KEY_JOY1+29, "JOY30"}, {KEY_JOY1+29, "joy30"},
{KEY_JOY1+30, "JOY31"}, {KEY_JOY1+30, "joy31"},
{KEY_JOY1+31, "JOY32"}, {KEY_JOY1+31, "joy32"},
#endif #endif
// the DOS version uses Allegro's joystick support // the DOS version uses Allegro's joystick support
{KEY_HAT1+0, "HATUP"}, {KEY_HAT1+0, "hatup"},
{KEY_HAT1+1, "HATDOWN"}, {KEY_HAT1+1, "hatdown"},
{KEY_HAT1+2, "HATLEFT"}, {KEY_HAT1+2, "hatleft"},
{KEY_HAT1+3, "HATRIGHT"}, {KEY_HAT1+3, "hatright"},
{KEY_HAT1+4, "HATUP2"}, {KEY_HAT1+4, "hatup2"},
{KEY_HAT1+5, "HATDOWN2"}, {KEY_HAT1+5, "hatdown2"},
{KEY_HAT1+6, "HATLEFT2"}, {KEY_HAT1+6, "hatleft2"},
{KEY_HAT1+7, "HATRIGHT2"}, {KEY_HAT1+7, "hatright2"},
{KEY_HAT1+8, "HATUP3"}, {KEY_HAT1+8, "hatup3"},
{KEY_HAT1+9, "HATDOWN3"}, {KEY_HAT1+9, "hatdown3"},
{KEY_HAT1+10, "HATLEFT3"}, {KEY_HAT1+10, "hatleft3"},
{KEY_HAT1+11, "HATRIGHT3"}, {KEY_HAT1+11, "hatright3"},
{KEY_HAT1+12, "HATUP4"}, {KEY_HAT1+12, "hatup4"},
{KEY_HAT1+13, "HATDOWN4"}, {KEY_HAT1+13, "hatdown4"},
{KEY_HAT1+14, "HATLEFT4"}, {KEY_HAT1+14, "hatleft4"},
{KEY_HAT1+15, "HATRIGHT4"}, {KEY_HAT1+15, "hatright4"},
{KEY_DBLMOUSE1+0, "DBLMOUSE1"}, {KEY_DBLMOUSE1+0, "dblmouse1"},
{KEY_DBLMOUSE1+1, "DBLMOUSE2"}, {KEY_DBLMOUSE1+1, "dblmouse2"},
{KEY_DBLMOUSE1+2, "DBLMOUSE3"}, {KEY_DBLMOUSE1+2, "dblmouse3"},
{KEY_DBLMOUSE1+3, "DBLMOUSE4"}, {KEY_DBLMOUSE1+3, "dblmouse4"},
{KEY_DBLMOUSE1+4, "DBLMOUSE5"}, {KEY_DBLMOUSE1+4, "dblmouse5"},
{KEY_DBLMOUSE1+5, "DBLMOUSE6"}, {KEY_DBLMOUSE1+5, "dblmouse6"},
{KEY_DBLMOUSE1+6, "DBLMOUSE7"}, {KEY_DBLMOUSE1+6, "dblmouse7"},
{KEY_DBLMOUSE1+7, "DBLMOUSE8"}, {KEY_DBLMOUSE1+7, "dblmouse8"},
{KEY_DBL2MOUSE1+0, "DBLSEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2 {KEY_DBL2MOUSE1+0, "dblsec_mouse2"}, // BP: sorry my mouse handler swap button 1 and 2
{KEY_DBL2MOUSE1+1, "DBLSEC_MOUSE1"}, {KEY_DBL2MOUSE1+1, "dblsec_mouse1"},
{KEY_DBL2MOUSE1+2, "DBLSEC_MOUSE3"}, {KEY_DBL2MOUSE1+2, "dblsec_mouse3"},
{KEY_DBL2MOUSE1+3, "DBLSEC_MOUSE4"}, {KEY_DBL2MOUSE1+3, "dblsec_mouse4"},
{KEY_DBL2MOUSE1+4, "DBLSEC_MOUSE5"}, {KEY_DBL2MOUSE1+4, "dblsec_mouse5"},
{KEY_DBL2MOUSE1+5, "DBLSEC_MOUSE6"}, {KEY_DBL2MOUSE1+5, "dblsec_mouse6"},
{KEY_DBL2MOUSE1+6, "DBLSEC_MOUSE7"}, {KEY_DBL2MOUSE1+6, "dblsec_mouse7"},
{KEY_DBL2MOUSE1+7, "DBLSEC_MOUSE8"}, {KEY_DBL2MOUSE1+7, "dblsec_mouse8"},
{KEY_DBLJOY1+0, "DBLJOY1"}, {KEY_DBLJOY1+0, "dbljoy1"},
{KEY_DBLJOY1+1, "DBLJOY2"}, {KEY_DBLJOY1+1, "dbljoy2"},
{KEY_DBLJOY1+2, "DBLJOY3"}, {KEY_DBLJOY1+2, "dbljoy3"},
{KEY_DBLJOY1+3, "DBLJOY4"}, {KEY_DBLJOY1+3, "dbljoy4"},
{KEY_DBLJOY1+4, "DBLJOY5"}, {KEY_DBLJOY1+4, "dbljoy5"},
{KEY_DBLJOY1+5, "DBLJOY6"}, {KEY_DBLJOY1+5, "dbljoy6"},
{KEY_DBLJOY1+6, "DBLJOY7"}, {KEY_DBLJOY1+6, "dbljoy7"},
{KEY_DBLJOY1+7, "DBLJOY8"}, {KEY_DBLJOY1+7, "dbljoy8"},
#if !defined (NOMOREJOYBTN_1DBL) #if !defined (NOMOREJOYBTN_1DBL)
{KEY_DBLJOY1+8, "DBLJOY9"}, {KEY_DBLJOY1+8, "dbljoy9"},
{KEY_DBLJOY1+9, "DBLJOY10"}, {KEY_DBLJOY1+9, "dbljoy10"},
{KEY_DBLJOY1+10, "DBLJOY11"}, {KEY_DBLJOY1+10, "dbljoy11"},
{KEY_DBLJOY1+11, "DBLJOY12"}, {KEY_DBLJOY1+11, "dbljoy12"},
{KEY_DBLJOY1+12, "DBLJOY13"}, {KEY_DBLJOY1+12, "dbljoy13"},
{KEY_DBLJOY1+13, "DBLJOY14"}, {KEY_DBLJOY1+13, "dbljoy14"},
{KEY_DBLJOY1+14, "DBLJOY15"}, {KEY_DBLJOY1+14, "dbljoy15"},
{KEY_DBLJOY1+15, "DBLJOY16"}, {KEY_DBLJOY1+15, "dbljoy16"},
{KEY_DBLJOY1+16, "DBLJOY17"}, {KEY_DBLJOY1+16, "dbljoy17"},
{KEY_DBLJOY1+17, "DBLJOY18"}, {KEY_DBLJOY1+17, "dbljoy18"},
{KEY_DBLJOY1+18, "DBLJOY19"}, {KEY_DBLJOY1+18, "dbljoy19"},
{KEY_DBLJOY1+19, "DBLJOY20"}, {KEY_DBLJOY1+19, "dbljoy20"},
{KEY_DBLJOY1+20, "DBLJOY21"}, {KEY_DBLJOY1+20, "dbljoy21"},
{KEY_DBLJOY1+21, "DBLJOY22"}, {KEY_DBLJOY1+21, "dbljoy22"},
{KEY_DBLJOY1+22, "DBLJOY23"}, {KEY_DBLJOY1+22, "dbljoy23"},
{KEY_DBLJOY1+23, "DBLJOY24"}, {KEY_DBLJOY1+23, "dbljoy24"},
{KEY_DBLJOY1+24, "DBLJOY25"}, {KEY_DBLJOY1+24, "dbljoy25"},
{KEY_DBLJOY1+25, "DBLJOY26"}, {KEY_DBLJOY1+25, "dbljoy26"},
{KEY_DBLJOY1+26, "DBLJOY27"}, {KEY_DBLJOY1+26, "dbljoy27"},
{KEY_DBLJOY1+27, "DBLJOY28"}, {KEY_DBLJOY1+27, "dbljoy28"},
{KEY_DBLJOY1+28, "DBLJOY29"}, {KEY_DBLJOY1+28, "dbljoy29"},
{KEY_DBLJOY1+29, "DBLJOY30"}, {KEY_DBLJOY1+29, "dbljoy30"},
{KEY_DBLJOY1+30, "DBLJOY31"}, {KEY_DBLJOY1+30, "dbljoy31"},
{KEY_DBLJOY1+31, "DBLJOY32"}, {KEY_DBLJOY1+31, "dbljoy32"},
#endif #endif
{KEY_DBLHAT1+0, "DBLHATUP"}, {KEY_DBLHAT1+0, "dblhatup"},
{KEY_DBLHAT1+1, "DBLHATDOWN"}, {KEY_DBLHAT1+1, "dblhatdown"},
{KEY_DBLHAT1+2, "DBLHATLEFT"}, {KEY_DBLHAT1+2, "dblhatleft"},
{KEY_DBLHAT1+3, "DBLHATRIGHT"}, {KEY_DBLHAT1+3, "dblhatright"},
{KEY_DBLHAT1+4, "DBLHATUP2"}, {KEY_DBLHAT1+4, "dblhatup2"},
{KEY_DBLHAT1+5, "DBLHATDOWN2"}, {KEY_DBLHAT1+5, "dblhatdown2"},
{KEY_DBLHAT1+6, "DBLHATLEFT2"}, {KEY_DBLHAT1+6, "dblhatleft2"},
{KEY_DBLHAT1+7, "DBLHATRIGHT2"}, {KEY_DBLHAT1+7, "dblhatright2"},
{KEY_DBLHAT1+8, "DBLHATUP3"}, {KEY_DBLHAT1+8, "dblhatup3"},
{KEY_DBLHAT1+9, "DBLHATDOWN3"}, {KEY_DBLHAT1+9, "dblhatdown3"},
{KEY_DBLHAT1+10, "DBLHATLEFT3"}, {KEY_DBLHAT1+10, "dblhatleft3"},
{KEY_DBLHAT1+11, "DBLHATRIGHT3"}, {KEY_DBLHAT1+11, "dblhatright3"},
{KEY_DBLHAT1+12, "DBLHATUP4"}, {KEY_DBLHAT1+12, "dblhatup4"},
{KEY_DBLHAT1+13, "DBLHATDOWN4"}, {KEY_DBLHAT1+13, "dblhatdown4"},
{KEY_DBLHAT1+14, "DBLHATLEFT4"}, {KEY_DBLHAT1+14, "dblhatleft4"},
{KEY_DBLHAT1+15, "DBLHATRIGHT4"}, {KEY_DBLHAT1+15, "dblhatright4"},
{KEY_2JOY1+0, "SEC_JOY1"}, {KEY_2JOY1+0, "sec_joy1"},
{KEY_2JOY1+1, "SEC_JOY2"}, {KEY_2JOY1+1, "sec_joy2"},
{KEY_2JOY1+2, "SEC_JOY3"}, {KEY_2JOY1+2, "sec_joy3"},
{KEY_2JOY1+3, "SEC_JOY4"}, {KEY_2JOY1+3, "sec_joy4"},
{KEY_2JOY1+4, "SEC_JOY5"}, {KEY_2JOY1+4, "sec_joy5"},
{KEY_2JOY1+5, "SEC_JOY6"}, {KEY_2JOY1+5, "sec_joy6"},
{KEY_2JOY1+6, "SEC_JOY7"}, {KEY_2JOY1+6, "sec_joy7"},
{KEY_2JOY1+7, "SEC_JOY8"}, {KEY_2JOY1+7, "sec_joy8"},
#if !defined (NOMOREJOYBTN_2S) #if !defined (NOMOREJOYBTN_2S)
// we use up to 32 buttons in DirectInput // we use up to 32 buttons in DirectInput
{KEY_2JOY1+8, "SEC_JOY9"}, {KEY_2JOY1+8, "sec_joy9"},
{KEY_2JOY1+9, "SEC_JOY10"}, {KEY_2JOY1+9, "sec_joy10"},
{KEY_2JOY1+10, "SEC_JOY11"}, {KEY_2JOY1+10, "sec_joy11"},
{KEY_2JOY1+11, "SEC_JOY12"}, {KEY_2JOY1+11, "sec_joy12"},
{KEY_2JOY1+12, "SEC_JOY13"}, {KEY_2JOY1+12, "sec_joy13"},
{KEY_2JOY1+13, "SEC_JOY14"}, {KEY_2JOY1+13, "sec_joy14"},
{KEY_2JOY1+14, "SEC_JOY15"}, {KEY_2JOY1+14, "sec_joy15"},
{KEY_2JOY1+15, "SEC_JOY16"}, {KEY_2JOY1+15, "sec_joy16"},
{KEY_2JOY1+16, "SEC_JOY17"}, {KEY_2JOY1+16, "sec_joy17"},
{KEY_2JOY1+17, "SEC_JOY18"}, {KEY_2JOY1+17, "sec_joy18"},
{KEY_2JOY1+18, "SEC_JOY19"}, {KEY_2JOY1+18, "sec_joy19"},
{KEY_2JOY1+19, "SEC_JOY20"}, {KEY_2JOY1+19, "sec_joy20"},
{KEY_2JOY1+20, "SEC_JOY21"}, {KEY_2JOY1+20, "sec_joy21"},
{KEY_2JOY1+21, "SEC_JOY22"}, {KEY_2JOY1+21, "sec_joy22"},
{KEY_2JOY1+22, "SEC_JOY23"}, {KEY_2JOY1+22, "sec_joy23"},
{KEY_2JOY1+23, "SEC_JOY24"}, {KEY_2JOY1+23, "sec_joy24"},
{KEY_2JOY1+24, "SEC_JOY25"}, {KEY_2JOY1+24, "sec_joy25"},
{KEY_2JOY1+25, "SEC_JOY26"}, {KEY_2JOY1+25, "sec_joy26"},
{KEY_2JOY1+26, "SEC_JOY27"}, {KEY_2JOY1+26, "sec_joy27"},
{KEY_2JOY1+27, "SEC_JOY28"}, {KEY_2JOY1+27, "sec_joy28"},
{KEY_2JOY1+28, "SEC_JOY29"}, {KEY_2JOY1+28, "sec_joy29"},
{KEY_2JOY1+29, "SEC_JOY30"}, {KEY_2JOY1+29, "sec_joy30"},
{KEY_2JOY1+30, "SEC_JOY31"}, {KEY_2JOY1+30, "sec_joy31"},
{KEY_2JOY1+31, "SEC_JOY32"}, {KEY_2JOY1+31, "sec_joy32"},
#endif #endif
// the DOS version uses Allegro's joystick support // the DOS version uses Allegro's joystick support
{KEY_2HAT1+0, "SEC_HATUP"}, {KEY_2HAT1+0, "sec_hatup"},
{KEY_2HAT1+1, "SEC_HATDOWN"}, {KEY_2HAT1+1, "sec_hatdown"},
{KEY_2HAT1+2, "SEC_HATLEFT"}, {KEY_2HAT1+2, "sec_hatleft"},
{KEY_2HAT1+3, "SEC_HATRIGHT"}, {KEY_2HAT1+3, "sec_hatright"},
{KEY_2HAT1+4, "SEC_HATUP2"}, {KEY_2HAT1+4, "sec_hatup2"},
{KEY_2HAT1+5, "SEC_HATDOWN2"}, {KEY_2HAT1+5, "sec_hatdown2"},
{KEY_2HAT1+6, "SEC_HATLEFT2"}, {KEY_2HAT1+6, "sec_hatleft2"},
{KEY_2HAT1+7, "SEC_HATRIGHT2"}, {KEY_2HAT1+7, "sec_hatright2"},
{KEY_2HAT1+8, "SEC_HATUP3"}, {KEY_2HAT1+8, "sec_hatup3"},
{KEY_2HAT1+9, "SEC_HATDOWN3"}, {KEY_2HAT1+9, "sec_hatdown3"},
{KEY_2HAT1+10, "SEC_HATLEFT3"}, {KEY_2HAT1+10, "sec_hatleft3"},
{KEY_2HAT1+11, "SEC_HATRIGHT3"}, {KEY_2HAT1+11, "sec_hatright3"},
{KEY_2HAT1+12, "SEC_HATUP4"}, {KEY_2HAT1+12, "sec_hatup4"},
{KEY_2HAT1+13, "SEC_HATDOWN4"}, {KEY_2HAT1+13, "sec_hatdown4"},
{KEY_2HAT1+14, "SEC_HATLEFT4"}, {KEY_2HAT1+14, "sec_hatleft4"},
{KEY_2HAT1+15, "SEC_HATRIGHT4"}, {KEY_2HAT1+15, "sec_hatright4"},
{KEY_DBL2JOY1+0, "DBLSEC_JOY1"}, {KEY_DBL2JOY1+0, "dblsec_joy1"},
{KEY_DBL2JOY1+1, "DBLSEC_JOY2"}, {KEY_DBL2JOY1+1, "dblsec_joy2"},
{KEY_DBL2JOY1+2, "DBLSEC_JOY3"}, {KEY_DBL2JOY1+2, "dblsec_joy3"},
{KEY_DBL2JOY1+3, "DBLSEC_JOY4"}, {KEY_DBL2JOY1+3, "dblsec_joy4"},
{KEY_DBL2JOY1+4, "DBLSEC_JOY5"}, {KEY_DBL2JOY1+4, "dblsec_joy5"},
{KEY_DBL2JOY1+5, "DBLSEC_JOY6"}, {KEY_DBL2JOY1+5, "dblsec_joy6"},
{KEY_DBL2JOY1+6, "DBLSEC_JOY7"}, {KEY_DBL2JOY1+6, "dblsec_joy7"},
{KEY_DBL2JOY1+7, "DBLSEC_JOY8"}, {KEY_DBL2JOY1+7, "dblsec_joy8"},
#if !defined (NOMOREJOYBTN_2DBL) #if !defined (NOMOREJOYBTN_2DBL)
{KEY_DBL2JOY1+8, "DBLSEC_JOY9"}, {KEY_DBL2JOY1+8, "dblsec_joy9"},
{KEY_DBL2JOY1+9, "DBLSEC_JOY10"}, {KEY_DBL2JOY1+9, "dblsec_joy10"},
{KEY_DBL2JOY1+10, "DBLSEC_JOY11"}, {KEY_DBL2JOY1+10, "dblsec_joy11"},
{KEY_DBL2JOY1+11, "DBLSEC_JOY12"}, {KEY_DBL2JOY1+11, "dblsec_joy12"},
{KEY_DBL2JOY1+12, "DBLSEC_JOY13"}, {KEY_DBL2JOY1+12, "dblsec_joy13"},
{KEY_DBL2JOY1+13, "DBLSEC_JOY14"}, {KEY_DBL2JOY1+13, "dblsec_joy14"},
{KEY_DBL2JOY1+14, "DBLSEC_JOY15"}, {KEY_DBL2JOY1+14, "dblsec_joy15"},
{KEY_DBL2JOY1+15, "DBLSEC_JOY16"}, {KEY_DBL2JOY1+15, "dblsec_joy16"},
{KEY_DBL2JOY1+16, "DBLSEC_JOY17"}, {KEY_DBL2JOY1+16, "dblsec_joy17"},
{KEY_DBL2JOY1+17, "DBLSEC_JOY18"}, {KEY_DBL2JOY1+17, "dblsec_joy18"},
{KEY_DBL2JOY1+18, "DBLSEC_JOY19"}, {KEY_DBL2JOY1+18, "dblsec_joy19"},
{KEY_DBL2JOY1+19, "DBLSEC_JOY20"}, {KEY_DBL2JOY1+19, "dblsec_joy20"},
{KEY_DBL2JOY1+20, "DBLSEC_JOY21"}, {KEY_DBL2JOY1+20, "dblsec_joy21"},
{KEY_DBL2JOY1+21, "DBLSEC_JOY22"}, {KEY_DBL2JOY1+21, "dblsec_joy22"},
{KEY_DBL2JOY1+22, "DBLSEC_JOY23"}, {KEY_DBL2JOY1+22, "dblsec_joy23"},
{KEY_DBL2JOY1+23, "DBLSEC_JOY24"}, {KEY_DBL2JOY1+23, "dblsec_joy24"},
{KEY_DBL2JOY1+24, "DBLSEC_JOY25"}, {KEY_DBL2JOY1+24, "dblsec_joy25"},
{KEY_DBL2JOY1+25, "DBLSEC_JOY26"}, {KEY_DBL2JOY1+25, "dblsec_joy26"},
{KEY_DBL2JOY1+26, "DBLSEC_JOY27"}, {KEY_DBL2JOY1+26, "dblsec_joy27"},
{KEY_DBL2JOY1+27, "DBLSEC_JOY28"}, {KEY_DBL2JOY1+27, "dblsec_joy28"},
{KEY_DBL2JOY1+28, "DBLSEC_JOY29"}, {KEY_DBL2JOY1+28, "dblsec_joy29"},
{KEY_DBL2JOY1+29, "DBLSEC_JOY30"}, {KEY_DBL2JOY1+29, "dblsec_joy30"},
{KEY_DBL2JOY1+30, "DBLSEC_JOY31"}, {KEY_DBL2JOY1+30, "dblsec_joy31"},
{KEY_DBL2JOY1+31, "DBLSEC_JOY32"}, {KEY_DBL2JOY1+31, "dblsec_joy32"},
#endif #endif
{KEY_DBL2HAT1+0, "DBLSEC_HATUP"}, {KEY_DBL2HAT1+0, "dblsec_hatup"},
{KEY_DBL2HAT1+1, "DBLSEC_HATDOWN"}, {KEY_DBL2HAT1+1, "dblsec_hatdown"},
{KEY_DBL2HAT1+2, "DBLSEC_HATLEFT"}, {KEY_DBL2HAT1+2, "dblsec_hatleft"},
{KEY_DBL2HAT1+3, "DBLSEC_HATRIGHT"}, {KEY_DBL2HAT1+3, "dblsec_hatright"},
{KEY_DBL2HAT1+4, "DBLSEC_HATUP2"}, {KEY_DBL2HAT1+4, "dblsec_hatup2"},
{KEY_DBL2HAT1+5, "DBLSEC_HATDOWN2"}, {KEY_DBL2HAT1+5, "dblsec_hatdown2"},
{KEY_DBL2HAT1+6, "DBLSEC_HATLEFT2"}, {KEY_DBL2HAT1+6, "dblsec_hatleft2"},
{KEY_DBL2HAT1+7, "DBLSEC_HATRIGHT2"}, {KEY_DBL2HAT1+7, "dblsec_hatright2"},
{KEY_DBL2HAT1+8, "DBLSEC_HATUP3"}, {KEY_DBL2HAT1+8, "dblsec_hatup3"},
{KEY_DBL2HAT1+9, "DBLSEC_HATDOWN3"}, {KEY_DBL2HAT1+9, "dblsec_hatdown3"},
{KEY_DBL2HAT1+10, "DBLSEC_HATLEFT3"}, {KEY_DBL2HAT1+10, "dblsec_hatleft3"},
{KEY_DBL2HAT1+11, "DBLSEC_HATRIGHT3"}, {KEY_DBL2HAT1+11, "dblsec_hatright3"},
{KEY_DBL2HAT1+12, "DBLSEC_HATUP4"}, {KEY_DBL2HAT1+12, "dblsec_hatup4"},
{KEY_DBL2HAT1+13, "DBLSEC_HATDOWN4"}, {KEY_DBL2HAT1+13, "dblsec_hatdown4"},
{KEY_DBL2HAT1+14, "DBLSEC_HATLEFT4"}, {KEY_DBL2HAT1+14, "dblsec_hatleft4"},
{KEY_DBL2HAT1+15, "DBLSEC_HATRIGHT4"}, {KEY_DBL2HAT1+15, "dblsec_hatright4"},
}; };

View file

@ -245,13 +245,16 @@ void HWR_RenderBatches(void)
currently_batching = false;// no longer collecting batches currently_batching = false;// no longer collecting batches
if (!polygonArraySize) if (!polygonArraySize)
{ {
ps_hw_numpolys = ps_hw_numcalls = ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 0; ps_hw_numpolys.value.i = ps_hw_numcalls.value.i = ps_hw_numshaders.value.i
= ps_hw_numtextures.value.i = ps_hw_numpolyflags.value.i
= ps_hw_numcolors.value.i = 0;
return;// nothing to draw return;// nothing to draw
} }
// init stats vars // init stats vars
ps_hw_numpolys = polygonArraySize; ps_hw_numpolys.value.i = polygonArraySize;
ps_hw_numcalls = ps_hw_numverts = 0; ps_hw_numcalls.value.i = ps_hw_numverts.value.i = 0;
ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 1; ps_hw_numshaders.value.i = ps_hw_numtextures.value.i
= ps_hw_numpolyflags.value.i = ps_hw_numcolors.value.i = 1;
// init polygonIndexArray // init polygonIndexArray
for (i = 0; i < polygonArraySize; i++) for (i = 0; i < polygonArraySize; i++)
{ {
@ -259,12 +262,12 @@ void HWR_RenderBatches(void)
} }
// sort polygons // sort polygons
ps_hw_batchsorttime = I_GetPreciseTime(); PS_START_TIMING(ps_hw_batchsorttime);
if (cv_glshaders.value && gl_shadersavailable) if (cv_glshaders.value && gl_shadersavailable)
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
else else
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
ps_hw_batchsorttime = I_GetPreciseTime() - ps_hw_batchsorttime; PS_STOP_TIMING(ps_hw_batchsorttime);
// sort order // sort order
// 1. shader // 1. shader
// 2. texture // 2. texture
@ -272,7 +275,7 @@ void HWR_RenderBatches(void)
// 4. colors + light level // 4. colors + light level
// not sure about what order of the last 2 should be, or if it even matters // not sure about what order of the last 2 should be, or if it even matters
ps_hw_batchdrawtime = I_GetPreciseTime(); PS_START_TIMING(ps_hw_batchdrawtime);
currentShader = polygonArray[polygonIndexArray[0]].shader; currentShader = polygonArray[polygonIndexArray[0]].shader;
currentTexture = polygonArray[polygonIndexArray[0]].texture; currentTexture = polygonArray[polygonIndexArray[0]].texture;
@ -408,8 +411,8 @@ void HWR_RenderBatches(void)
// execute draw call // execute draw call
HWD.pfnDrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); HWD.pfnDrawIndexedTriangles(&currentSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray);
// update stats // update stats
ps_hw_numcalls++; ps_hw_numcalls.value.i++;
ps_hw_numverts += finalIndexWritePos; ps_hw_numverts.value.i += finalIndexWritePos;
// reset write positions // reset write positions
finalVertexWritePos = 0; finalVertexWritePos = 0;
finalIndexWritePos = 0; finalIndexWritePos = 0;
@ -426,7 +429,7 @@ void HWR_RenderBatches(void)
currentShader = nextShader; currentShader = nextShader;
changeShader = false; changeShader = false;
ps_hw_numshaders++; ps_hw_numshaders.value.i++;
} }
if (changeTexture) if (changeTexture)
{ {
@ -435,21 +438,21 @@ void HWR_RenderBatches(void)
currentTexture = nextTexture; currentTexture = nextTexture;
changeTexture = false; changeTexture = false;
ps_hw_numtextures++; ps_hw_numtextures.value.i++;
} }
if (changePolyFlags) if (changePolyFlags)
{ {
currentPolyFlags = nextPolyFlags; currentPolyFlags = nextPolyFlags;
changePolyFlags = false; changePolyFlags = false;
ps_hw_numpolyflags++; ps_hw_numpolyflags.value.i++;
} }
if (changeSurfaceInfo) if (changeSurfaceInfo)
{ {
currentSurfaceInfo = nextSurfaceInfo; currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false; changeSurfaceInfo = false;
ps_hw_numcolors++; ps_hw_numcolors.value.i++;
} }
// and that should be it? // and that should be it?
} }
@ -457,7 +460,7 @@ void HWR_RenderBatches(void)
polygonArraySize = 0; polygonArraySize = 0;
unsortedVertexArraySize = 0; unsortedVertexArraySize = 0;
ps_hw_batchdrawtime = I_GetPreciseTime() - ps_hw_batchdrawtime; PS_STOP_TIMING(ps_hw_batchdrawtime);
} }

View file

@ -147,22 +147,22 @@ static angle_t gl_aimingangle;
static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox); static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox);
// Render stats // Render stats
precise_t ps_hw_skyboxtime = 0; ps_metric_t ps_hw_skyboxtime = {0};
precise_t ps_hw_nodesorttime = 0; ps_metric_t ps_hw_nodesorttime = {0};
precise_t ps_hw_nodedrawtime = 0; ps_metric_t ps_hw_nodedrawtime = {0};
precise_t ps_hw_spritesorttime = 0; ps_metric_t ps_hw_spritesorttime = {0};
precise_t ps_hw_spritedrawtime = 0; ps_metric_t ps_hw_spritedrawtime = {0};
// Render stats for batching // Render stats for batching
int ps_hw_numpolys = 0; ps_metric_t ps_hw_numpolys = {0};
int ps_hw_numverts = 0; ps_metric_t ps_hw_numverts = {0};
int ps_hw_numcalls = 0; ps_metric_t ps_hw_numcalls = {0};
int ps_hw_numshaders = 0; ps_metric_t ps_hw_numshaders = {0};
int ps_hw_numtextures = 0; ps_metric_t ps_hw_numtextures = {0};
int ps_hw_numpolyflags = 0; ps_metric_t ps_hw_numpolyflags = {0};
int ps_hw_numcolors = 0; ps_metric_t ps_hw_numcolors = {0};
precise_t ps_hw_batchsorttime = 0; ps_metric_t ps_hw_batchsorttime = {0};
precise_t ps_hw_batchdrawtime = 0; ps_metric_t ps_hw_batchdrawtime = {0};
boolean gl_init = false; boolean gl_init = false;
boolean gl_maploaded = false; boolean gl_maploaded = false;
@ -3235,7 +3235,7 @@ static void HWR_Subsector(size_t num)
} }
// for render stats // for render stats
ps_numpolyobjects += numpolys; ps_numpolyobjects.value.i += numpolys;
// Sort polyobjects // Sort polyobjects
R_SortPolyObjects(sub); R_SortPolyObjects(sub);
@ -3343,7 +3343,7 @@ static void HWR_RenderBSPNode(INT32 bspnum)
// Decide which side the view point is on // Decide which side the view point is on
INT32 side; INT32 side;
ps_numbspcalls++; ps_numbspcalls.value.i++;
// Found a subsector? // Found a subsector?
if (bspnum & NF_SUBSECTOR) if (bspnum & NF_SUBSECTOR)
@ -4718,7 +4718,7 @@ static void HWR_CreateDrawNodes(void)
// that is already lying around. This should all be in some sort of linked list or lists. // that is already lying around. This should all be in some sort of linked list or lists.
sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL); sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL);
ps_hw_nodesorttime = I_GetPreciseTime(); PS_START_TIMING(ps_hw_nodesorttime);
for (i = 0; i < numplanes; i++, p++) for (i = 0; i < numplanes; i++, p++)
{ {
@ -4738,7 +4738,7 @@ static void HWR_CreateDrawNodes(void)
sortindex[p] = p; sortindex[p] = p;
} }
ps_numdrawnodes = p; ps_numdrawnodes.value.i = p;
// p is the number of stuff to sort // p is the number of stuff to sort
@ -4773,9 +4773,9 @@ static void HWR_CreateDrawNodes(void)
} }
} }
ps_hw_nodesorttime = I_GetPreciseTime() - ps_hw_nodesorttime; PS_STOP_TIMING(ps_hw_nodesorttime);
ps_hw_nodedrawtime = I_GetPreciseTime(); PS_START_TIMING(ps_hw_nodedrawtime);
// Okay! Let's draw it all! Woo! // Okay! Let's draw it all! Woo!
HWD.pfnSetTransform(&atransform); HWD.pfnSetTransform(&atransform);
@ -4812,7 +4812,7 @@ static void HWR_CreateDrawNodes(void)
} }
} }
ps_hw_nodedrawtime = I_GetPreciseTime() - ps_hw_nodedrawtime; PS_STOP_TIMING(ps_hw_nodedrawtime);
numwalls = 0; numwalls = 0;
numplanes = 0; numplanes = 0;
@ -6095,10 +6095,10 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
if (viewnumber == 0) // Only do it if it's the first screen being rendered if (viewnumber == 0) // Only do it if it's the first screen being rendered
HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs.
ps_hw_skyboxtime = I_GetPreciseTime(); PS_START_TIMING(ps_hw_skyboxtime);
if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox
HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind
ps_hw_skyboxtime = I_GetPreciseTime() - ps_hw_skyboxtime; PS_STOP_TIMING(ps_hw_skyboxtime);
{ {
// do we really need to save player (is it not the same)? // do we really need to save player (is it not the same)?
@ -6208,9 +6208,9 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
// Reset the shader state. // Reset the shader state.
HWR_SetShaderState(); HWR_SetShaderState();
ps_numbspcalls = 0; ps_numbspcalls.value.i = 0;
ps_numpolyobjects = 0; ps_numpolyobjects.value.i = 0;
ps_bsptime = I_GetPreciseTime(); PS_START_TIMING(ps_bsptime);
validcount++; validcount++;
@ -6248,7 +6248,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
} }
#endif #endif
ps_bsptime = I_GetPreciseTime() - ps_bsptime; PS_STOP_TIMING(ps_bsptime);
if (cv_glbatching.value) if (cv_glbatching.value)
HWR_RenderBatches(); HWR_RenderBatches();
@ -6263,22 +6263,22 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
#endif #endif
// Draw MD2 and sprites // Draw MD2 and sprites
ps_numsprites = gl_visspritecount; ps_numsprites.value.i = gl_visspritecount;
ps_hw_spritesorttime = I_GetPreciseTime(); PS_START_TIMING(ps_hw_spritesorttime);
HWR_SortVisSprites(); HWR_SortVisSprites();
ps_hw_spritesorttime = I_GetPreciseTime() - ps_hw_spritesorttime; PS_STOP_TIMING(ps_hw_spritesorttime);
ps_hw_spritedrawtime = I_GetPreciseTime(); PS_START_TIMING(ps_hw_spritedrawtime);
HWR_DrawSprites(); HWR_DrawSprites();
ps_hw_spritedrawtime = I_GetPreciseTime() - ps_hw_spritedrawtime; PS_STOP_TIMING(ps_hw_spritedrawtime);
#ifdef NEWCORONAS #ifdef NEWCORONAS
//Hurdler: they must be drawn before translucent planes, what about gl fog? //Hurdler: they must be drawn before translucent planes, what about gl fog?
HWR_DrawCoronas(); HWR_DrawCoronas();
#endif #endif
ps_numdrawnodes = 0; ps_numdrawnodes.value.i = 0;
ps_hw_nodesorttime = 0; ps_hw_nodesorttime.value.p = 0;
ps_hw_nodedrawtime = 0; ps_hw_nodedrawtime.value.p = 0;
if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything
{ {
HWR_CreateDrawNodes(); HWR_CreateDrawNodes();

View file

@ -20,6 +20,8 @@
#include "../d_player.h" #include "../d_player.h"
#include "../r_defs.h" #include "../r_defs.h"
#include "../m_perfstats.h"
// Startup & Shutdown the hardware mode renderer // Startup & Shutdown the hardware mode renderer
void HWR_Startup(void); void HWR_Startup(void);
void HWR_Switch(void); void HWR_Switch(void);
@ -116,22 +118,22 @@ extern FTransform atransform;
// Render stats // Render stats
extern precise_t ps_hw_skyboxtime; extern ps_metric_t ps_hw_skyboxtime;
extern precise_t ps_hw_nodesorttime; extern ps_metric_t ps_hw_nodesorttime;
extern precise_t ps_hw_nodedrawtime; extern ps_metric_t ps_hw_nodedrawtime;
extern precise_t ps_hw_spritesorttime; extern ps_metric_t ps_hw_spritesorttime;
extern precise_t ps_hw_spritedrawtime; extern ps_metric_t ps_hw_spritedrawtime;
// Render stats for batching // Render stats for batching
extern int ps_hw_numpolys; extern ps_metric_t ps_hw_numpolys;
extern int ps_hw_numverts; extern ps_metric_t ps_hw_numverts;
extern int ps_hw_numcalls; extern ps_metric_t ps_hw_numcalls;
extern int ps_hw_numshaders; extern ps_metric_t ps_hw_numshaders;
extern int ps_hw_numtextures; extern ps_metric_t ps_hw_numtextures;
extern int ps_hw_numpolyflags; extern ps_metric_t ps_hw_numpolyflags;
extern int ps_hw_numcolors; extern ps_metric_t ps_hw_numcolors;
extern precise_t ps_hw_batchsorttime; extern ps_metric_t ps_hw_batchsorttime;
extern precise_t ps_hw_batchdrawtime; extern ps_metric_t ps_hw_batchdrawtime;
extern boolean gl_init; extern boolean gl_init;
extern boolean gl_maploaded; extern boolean gl_maploaded;

View file

@ -50,7 +50,7 @@ tic_t I_GetTime(void);
*/ */
precise_t I_GetPreciseTime(void); precise_t I_GetPreciseTime(void);
/** \brief Returns the difference between precise times as microseconds. /** \brief Converts a precise_t to microseconds and casts it to a 32 bit integer.
*/ */
int I_PreciseToMicros(precise_t); int I_PreciseToMicros(precise_t);
@ -318,10 +318,6 @@ void I_RegisterSysCommands(void);
*/ */
void I_GetCursorPosition(INT32 *x, INT32 *y); void I_GetCursorPosition(INT32 *x, INT32 *y);
/** \brief Returns whether the mouse is grabbed
*/
boolean I_GetMouseGrab(void);
/** \brief Sets whether the mouse is grabbed /** \brief Sets whether the mouse is grabbed
*/ */
void I_SetMouseGrab(boolean grab); void I_SetMouseGrab(boolean grab);

View file

@ -2069,7 +2069,7 @@ state_t states[NUMSTATES] =
{SPR_TVFL, 2, 18, {A_GiveShield}, SH_FLAMEAURA, 0, S_NULL}, // S_FLAMEAURA_ICON2 {SPR_TVFL, 2, 18, {A_GiveShield}, SH_FLAMEAURA, 0, S_NULL}, // S_FLAMEAURA_ICON2
{SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1 {SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1
{SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLERWAP_ICON2 {SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLEWRAP_ICON2
{SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1 {SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1
{SPR_TVZP, 2, 18, {A_GiveShield}, SH_THUNDERCOIN, 0, S_NULL}, // S_THUNDERCOIN_ICON2 {SPR_TVZP, 2, 18, {A_GiveShield}, SH_THUNDERCOIN, 0, S_NULL}, // S_THUNDERCOIN_ICON2
@ -5199,7 +5199,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
24*FRACUNIT, // radius 24*FRACUNIT, // radius
34*FRACUNIT, // height 34*FRACUNIT, // height
0, // display offset 0, // display offset
100, // mass DMG_FIRE, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_FIRE|MF_PAIN, // flags MF_NOGRAVITY|MF_NOBLOCKMAP|MF_FIRE|MF_PAIN, // flags
@ -7974,7 +7974,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
8*FRACUNIT, // radius 8*FRACUNIT, // radius
32*FRACUNIT, // height 32*FRACUNIT, // height
0, // display offset 0, // display offset
4, // mass DMG_SPIKE, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
@ -8001,7 +8001,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
16*FRACUNIT, // radius 16*FRACUNIT, // radius
14*FRACUNIT, // height 14*FRACUNIT, // height
0, // display offset 0, // display offset
4, // mass DMG_SPIKE, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION, // flags MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION, // flags
@ -11430,7 +11430,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
17*FRACUNIT, // radius 17*FRACUNIT, // radius
34*FRACUNIT, // height 34*FRACUNIT, // height
1, // display offset 1, // display offset
0, // mass DMG_SPIKE, // mass
1, // damage 1, // damage
sfx_s3kc9s, //sfx_mswing, -- activesound sfx_s3kc9s, //sfx_mswing, -- activesound
MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
@ -11457,7 +11457,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
34*FRACUNIT, // radius 34*FRACUNIT, // radius
68*FRACUNIT, // height 68*FRACUNIT, // height
1, // display offset 1, // display offset
0, // mass DMG_SPIKE, // mass
1, // damage 1, // damage
sfx_s3kc9s, //sfx_mswing, -- activesound sfx_s3kc9s, //sfx_mswing, -- activesound
MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
@ -13401,7 +13401,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
30*FRACUNIT, // radius 30*FRACUNIT, // radius
48*FRACUNIT, // height 48*FRACUNIT, // height
0, // display offset 0, // display offset
100, // mass DMG_FIRE, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_SPECIAL|MF_PAIN|MF_NOGRAVITY|MF_FIRE, // flags MF_SPECIAL|MF_PAIN|MF_NOGRAVITY|MF_FIRE, // flags
@ -13806,7 +13806,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
8*FRACUNIT, // radius 8*FRACUNIT, // radius
32*FRACUNIT, // height 32*FRACUNIT, // height
0, // display offset 0, // display offset
0, // mass 0, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOGRAVITY|MF_PAIN, // flags MF_NOGRAVITY|MF_PAIN, // flags
@ -20380,7 +20380,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
18*FRACUNIT, // radius 18*FRACUNIT, // radius
28*FRACUNIT, // height 28*FRACUNIT, // height
0, // display offset 0, // display offset
0, // mass DMG_SPIKE, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOGRAVITY|MF_PAIN, // flags MF_NOGRAVITY|MF_PAIN, // flags

View file

@ -31,6 +31,7 @@
#include "m_misc.h" // M_MapNumber #include "m_misc.h" // M_MapNumber
#include "b_bot.h" // B_UpdateBotleader #include "b_bot.h" // B_UpdateBotleader
#include "d_clisrv.h" // CL_RemovePlayer #include "d_clisrv.h" // CL_RemovePlayer
#include "i_system.h" // I_GetPreciseTime, I_PreciseToMicros
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
@ -187,6 +188,8 @@ static const struct {
{META_MAPHEADER, "mapheader_t"}, {META_MAPHEADER, "mapheader_t"},
{META_POLYOBJ, "polyobj_t"}, {META_POLYOBJ, "polyobj_t"},
{META_POLYOBJVERTICES, "polyobj_t.vertices"},
{META_POLYOBJLINES, "polyobj_t.lines"},
{META_CVAR, "consvar_t"}, {META_CVAR, "consvar_t"},
@ -216,6 +219,7 @@ static const struct {
{META_LUABANKS, "luabanks[]"}, {META_LUABANKS, "luabanks[]"},
{META_KEYEVENT, "keyevent_t"},
{META_MOUSE, "mouse_t"}, {META_MOUSE, "mouse_t"},
{NULL, NULL} {NULL, NULL}
}; };
@ -3877,6 +3881,12 @@ static int lib_gTicsToMilliseconds(lua_State *L)
return 1; return 1;
} }
static int lib_getTimeMicros(lua_State *L)
{
lua_pushinteger(L, I_PreciseToMicros(I_GetPreciseTime()));
return 1;
}
static luaL_Reg lib[] = { static luaL_Reg lib[] = {
{"print", lib_print}, {"print", lib_print},
{"chatprint", lib_chatprint}, {"chatprint", lib_chatprint},
@ -4151,6 +4161,8 @@ static luaL_Reg lib[] = {
{"G_TicsToCentiseconds",lib_gTicsToCentiseconds}, {"G_TicsToCentiseconds",lib_gTicsToCentiseconds},
{"G_TicsToMilliseconds",lib_gTicsToMilliseconds}, {"G_TicsToMilliseconds",lib_gTicsToMilliseconds},
{"getTimeMicros",lib_getTimeMicros},
{NULL, NULL} {NULL, NULL}
}; };

View file

@ -505,7 +505,7 @@ static int call_hooks
calls += call_mobj_type_hooks(hook, MT_NULL); calls += call_mobj_type_hooks(hook, MT_NULL);
calls += call_mobj_type_hooks(hook, hook->mobj_type); calls += call_mobj_type_hooks(hook, hook->mobj_type);
ps_lua_mobjhooks += calls; ps_lua_mobjhooks.value.i += calls;
} }
else else
calls += call_mapped(hook, &hookIds[hook->hook_type]); calls += call_mapped(hook, &hookIds[hook->hook_type]);
@ -868,7 +868,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
LUA_PushUserdata(gL, line, META_LINE); LUA_PushUserdata(gL, line, META_LINE);
LUA_PushUserdata(gL, mo, META_MOBJ); LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_PushUserdata(gL, sector, META_SECTOR); LUA_PushUserdata(gL, sector, META_SECTOR);
ps_lua_mobjhooks += call_hooks(&hook, 0, res_none); ps_lua_mobjhooks.value.i += call_hooks(&hook, 0, res_none);
} }
} }

View file

@ -265,7 +265,7 @@ static int hudinfo_num(lua_State *L)
static int colormap_get(lua_State *L) static int colormap_get(lua_State *L)
{ {
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
UINT32 i = luaL_checkinteger(L, 2); UINT32 i = luaL_checkinteger(L, 2);
if (i >= 256) if (i >= 256)
return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255); return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
@ -273,23 +273,6 @@ static int colormap_get(lua_State *L)
return 1; return 1;
} }
static int colormap_set(lua_State *L)
{
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
UINT32 i = luaL_checkinteger(L, 2);
if (i >= 256)
return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
colormap[i] = (UINT8)luaL_checkinteger(L, 3);
return 0;
}
static int colormap_free(lua_State *L)
{
UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
Z_Free(colormap);
return 0;
}
static int patch_get(lua_State *L) static int patch_get(lua_State *L)
{ {
patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH));
@ -1057,7 +1040,7 @@ static int libd_getColormap(lua_State *L)
// all was successful above, now we generate the colormap at last! // all was successful above, now we generate the colormap at last!
colormap = R_GetTranslationColormap(skinnum, color, 0); colormap = R_GetTranslationColormap(skinnum, color, GTC_CACHE);
LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use! LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1; return 1;
} }
@ -1066,14 +1049,10 @@ static int libd_getStringColormap(lua_State *L)
{ {
INT32 flags = luaL_checkinteger(L, 1); INT32 flags = luaL_checkinteger(L, 1);
UINT8* colormap = NULL; UINT8* colormap = NULL;
UINT8* lua_colormap = NULL;
HUDONLY HUDONLY
colormap = V_GetStringColormap(flags & V_CHARCOLORMASK); colormap = V_GetStringColormap(flags & V_CHARCOLORMASK);
if (colormap) { if (colormap) {
lua_colormap = Z_Malloc(256 * sizeof(UINT8), PU_LUA, NULL); LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
memcpy(lua_colormap, colormap, 256 * sizeof(UINT8));
LUA_PushUserdata(L, lua_colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use!
return 1; return 1;
} }
return 0; return 0;
@ -1348,12 +1327,6 @@ int LUA_HudLib(lua_State *L)
luaL_newmetatable(L, META_COLORMAP); luaL_newmetatable(L, META_COLORMAP);
lua_pushcfunction(L, colormap_get); lua_pushcfunction(L, colormap_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");
lua_pushcfunction(L, colormap_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, colormap_free);
lua_setfield(L, -2, "__gc");
lua_pop(L,1); lua_pop(L,1);
luaL_newmetatable(L, META_PATCH); luaL_newmetatable(L, META_PATCH);

View file

@ -204,7 +204,7 @@ enum ffloor_e {
ffloor_next, ffloor_next,
ffloor_prev, ffloor_prev,
ffloor_alpha, ffloor_alpha,
ffloor_specialflags, ffloor_bustflags,
ffloor_busttype, ffloor_busttype,
ffloor_busttag, ffloor_busttag,
ffloor_sinkspeed, ffloor_sinkspeed,
@ -228,7 +228,7 @@ static const char *const ffloor_opt[] = {
"next", "next",
"prev", "prev",
"alpha", "alpha",
"specialflags", "bustflags",
"busttype", "busttype",
"busttag", "busttag",
"sinkspeed", "sinkspeed",
@ -1851,8 +1851,8 @@ static int ffloor_get(lua_State *L)
case ffloor_alpha: case ffloor_alpha:
lua_pushinteger(L, ffloor->alpha); lua_pushinteger(L, ffloor->alpha);
return 1; return 1;
case ffloor_specialflags: case ffloor_bustflags:
lua_pushinteger(L, ffloor->specialflags); lua_pushinteger(L, ffloor->bustflags);
return 1; return 1;
case ffloor_busttype: case ffloor_busttype:
lua_pushinteger(L, ffloor->busttype); lua_pushinteger(L, ffloor->busttype);

View file

@ -3215,7 +3215,7 @@ boolean M_Responder(event_t *ev)
if (gamestate == GS_TITLESCREEN && finalecount < TICRATE) if (gamestate == GS_TITLESCREEN && finalecount < TICRATE)
return false; return false;
if (CON_Ready()) if (CON_Ready() && gamestate != GS_WAITINGPLAYERS)
return false; return false;
if (noFurtherInput) if (noFurtherInput)
@ -4062,14 +4062,6 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop)
for (i = 1; i < SLIDER_RANGE; i++) for (i = 1; i < SLIDER_RANGE; i++)
V_DrawScaledPatch (x+i*8, y, 0,p); V_DrawScaledPatch (x+i*8, y, 0,p);
if (ontop)
{
V_DrawCharacter(x - 6 - (skullAnimCounter/5), y,
'\x1C' | V_YELLOWMAP, false);
V_DrawCharacter(x+i*8 + 8 + (skullAnimCounter/5), y,
'\x1D' | V_YELLOWMAP, false);
}
p = W_CachePatchName("M_SLIDER", PU_PATCH); p = W_CachePatchName("M_SLIDER", PU_PATCH);
V_DrawScaledPatch(x+i*8, y, 0, p); V_DrawScaledPatch(x+i*8, y, 0, p);
@ -4105,6 +4097,16 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop)
range = 100; range = 100;
V_DrawMappedPatch(x + 2 + (SLIDER_RANGE*8*range)/100, y, 0, p, yellowmap); V_DrawMappedPatch(x + 2 + (SLIDER_RANGE*8*range)/100, y, 0, p, yellowmap);
if (ontop)
{
V_DrawCharacter(x - 6 - (skullAnimCounter/5), y,
'\x1C' | V_YELLOWMAP, false);
V_DrawCharacter(x + 80 + (skullAnimCounter/5), y,
'\x1D' | V_YELLOWMAP, false);
V_DrawCenteredString(x + 40, y, V_30TRANS,
(cv->flags & CV_FLOAT) ? va("%.2f", FIXED_TO_FLOAT(cv->value)) : va("%d", cv->value));
}
} }
// //
@ -6410,6 +6412,7 @@ static void M_Addons(INT32 choice)
M_SetupNextMenu(&MISC_AddonsDef); M_SetupNextMenu(&MISC_AddonsDef);
} }
#ifdef ENFORCE_WAD_LIMIT
#define width 4 #define width 4
#define vpadding 27 #define vpadding 27
#define h (BASEVIDHEIGHT-(2*vpadding)) #define h (BASEVIDHEIGHT-(2*vpadding))
@ -6457,6 +6460,7 @@ static void M_DrawTemperature(INT32 x, fixed_t t)
#undef vpadding #undef vpadding
#undef h #undef h
#undef NUMCOLOURS #undef NUMCOLOURS
#endif
static char *M_AddonsHeaderPath(void) static char *M_AddonsHeaderPath(void)
{ {
@ -6550,21 +6554,20 @@ static void M_DrawAddons(void)
V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, LOCATIONSTRING1); V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, LOCATIONSTRING1);
// (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1) // (recommendedflags == V_SKYMAP ? LOCATIONSTRING2 : LOCATIONSTRING1)
#ifdef ENFORCE_WAD_LIMIT
if (numwadfiles <= mainwads+1) if (numwadfiles <= mainwads+1)
y = 0; y = 0;
else if (numwadfiles >= MAX_WADFILES) else if (numwadfiles >= MAX_WADFILES)
y = FRACUNIT; y = FRACUNIT;
else else
{ {
x = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))<<FRACBITS, ((ssize_t)MAX_WADFILES - (ssize_t)(mainwads+1))<<FRACBITS); y = FixedDiv(((ssize_t)(numwadfiles) - (ssize_t)(mainwads+1))<<FRACBITS, ((ssize_t)MAX_WADFILES - (ssize_t)(mainwads+1))<<FRACBITS);
y = FixedDiv((((ssize_t)packetsizetally-(ssize_t)mainwadstally)<<FRACBITS), ((((ssize_t)MAXFILENEEDED*sizeof(UINT8)-(ssize_t)mainwadstally)-(5+22))<<FRACBITS)); // 5+22 = (a.ext + checksum length) is minimum addition to packet size tally
if (x > y)
y = x;
if (y > FRACUNIT) // happens because of how we're shrinkin' it a little if (y > FRACUNIT) // happens because of how we're shrinkin' it a little
y = FRACUNIT; y = FRACUNIT;
} }
M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y); M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y);
#endif
// DRAW MENU // DRAW MENU
x = currentMenu->x; x = currentMenu->x;
@ -7187,13 +7190,20 @@ static void M_HandleChecklist(INT32 choice)
static void M_DrawChecklist(void) static void M_DrawChecklist(void)
{ {
INT32 i = check_on, j = 0, y = currentMenu->y; INT32 i = check_on, j = 0, y = currentMenu->y, emblems = numemblems+numextraemblems;
UINT32 condnum, previd, maxcond; UINT32 condnum, previd, maxcond;
condition_t *cond; condition_t *cond;
// draw title (or big pic) // draw title (or big pic)
M_DrawMenuTitle(); M_DrawMenuTitle();
// draw emblem counter
if (emblems > 0)
{
V_DrawString(42, 20, (emblems == M_CountEmblems()) ? V_GREENMAP : 0, va("%d/%d", M_CountEmblems(), emblems));
V_DrawSmallScaledPatch(28, 20, 0, W_CachePatchName("EMBLICON", PU_PATCH));
}
if (check_on) if (check_on)
V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A"); V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A");
@ -8652,6 +8662,12 @@ static void M_DrawLoad(void)
loadgameoffset = 0; loadgameoffset = 0;
M_DrawLoadGameData(); M_DrawLoadGameData();
if (modifiedgame && !savemoddata)
{
V_DrawCenteredThinString(BASEVIDWIDTH/2, 184, 0, "\x85WARNING: \x80The game is modified.");
V_DrawCenteredThinString(BASEVIDWIDTH/2, 192, 0, "Progress will not be saved.");
}
} }
// //
@ -8953,7 +8969,7 @@ static void M_HandleLoadSave(INT32 choice)
break; break;
case KEY_ENTER: case KEY_ENTER:
if (ultimate_selectable && saveSlotSelected == NOSAVESLOT) if (ultimate_selectable && saveSlotSelected == NOSAVESLOT && !savemoddata && !modifiedgame)
{ {
loadgamescroll = 0; loadgamescroll = 0;
S_StartSound(NULL, sfx_skid); S_StartSound(NULL, sfx_skid);

File diff suppressed because it is too large Load diff

View file

@ -16,26 +16,45 @@
#include "lua_script.h" #include "lua_script.h"
#include "p_local.h" #include "p_local.h"
extern precise_t ps_tictime; typedef struct
{
extern precise_t ps_playerthink_time; union {
extern precise_t ps_thinkertime; precise_t p;
INT32 i;
extern precise_t ps_thlist_times[]; } value;
void *history;
extern int ps_checkposition_calls; } ps_metric_t;
extern precise_t ps_lua_thinkframe_time;
extern int ps_lua_mobjhooks;
typedef struct typedef struct
{ {
precise_t time_taken; ps_metric_t time_taken;
char short_src[LUA_IDSIZE]; char short_src[LUA_IDSIZE];
} ps_hookinfo_t; } ps_hookinfo_t;
#define PS_START_TIMING(metric) metric.value.p = I_GetPreciseTime()
#define PS_STOP_TIMING(metric) metric.value.p = I_GetPreciseTime() - metric.value.p
extern ps_metric_t ps_tictime;
extern ps_metric_t ps_playerthink_time;
extern ps_metric_t ps_thinkertime;
extern ps_metric_t ps_thlist_times[];
extern ps_metric_t ps_checkposition_calls;
extern ps_metric_t ps_lua_thinkframe_time;
extern ps_metric_t ps_lua_mobjhooks;
extern ps_metric_t ps_otherlogictime;
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
void PS_UpdateTickStats(void);
void M_DrawPerfStats(void); void M_DrawPerfStats(void);
void PS_PerfStats_OnChange(void);
void PS_SampleSize_OnChange(void);
#endif #endif

View file

@ -3518,9 +3518,7 @@ void A_Scream(mobj_t *actor)
if (LUA_CallAction(A_SCREAM, actor)) if (LUA_CallAction(A_SCREAM, actor))
return; return;
if (actor->tracer && (actor->tracer->type == MT_SHELL || actor->tracer->type == MT_FIREBALL)) if (actor->info->deathsound && !S_SoundPlaying(actor, sfx_mario2))
S_StartScreamSound(actor, sfx_mario2);
else if (actor->info->deathsound)
S_StartScreamSound(actor, actor->info->deathsound); S_StartScreamSound(actor, actor->info->deathsound);
} }
@ -5284,7 +5282,7 @@ void A_OverlayThink(mobj_t *actor)
actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT;
else else
actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT;
actor->angle = actor->target->angle + actor->movedir; actor->angle = (actor->target->player ? actor->target->player->drawangle : actor->target->angle) + actor->movedir;
actor->eflags = actor->target->eflags; actor->eflags = actor->target->eflags;
actor->momx = actor->target->momx; actor->momx = actor->target->momx;

View file

@ -988,6 +988,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
case MT_THUNDERCOIN_ORB: case MT_THUNDERCOIN_ORB:
case MT_IVSP: case MT_IVSP:
case MT_SUPERSPARK: case MT_SUPERSPARK:
case MT_BOXSPARKLE:
case MT_RAIN: case MT_RAIN:
case MT_SNOWFLAKE: case MT_SNOWFLAKE:
case MT_SPLISH: case MT_SPLISH:

View file

@ -2385,7 +2385,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mobj_t *mo; mobj_t *mo;
if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL)) if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL))
P_SetTarget(&target->tracer, inflictor); S_StartScreamSound(target, sfx_mario2);
if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && target->player && target->player->nightstime > 6) if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && target->player && target->player->nightstime > 6)
target->player->nightstime = 6; // Just let P_Ticker take care of the rest. target->player->nightstime = 6; // Just let P_Ticker take care of the rest.
@ -3645,7 +3645,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return true; return true;
} }
if (!force && inflictor && inflictor->flags & MF_FIRE) if (!force && inflictor && inflictor->flags & MF_FIRE && !(damagetype && damagetype != DMG_FIRE))
{ {
if (player->powers[pw_shield] & SH_PROTECTFIRE) if (player->powers[pw_shield] & SH_PROTECTFIRE)
return false; // Invincible to fire objects return false; // Invincible to fire objects

View file

@ -1156,7 +1156,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else else
thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale); thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
if (thing->flags & MF_SHOOTABLE) if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, tmthing, tmthing, 1, 0); P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
return true; return true;
} }
@ -2029,7 +2029,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
subsector_t *newsubsec; subsector_t *newsubsec;
boolean blockval = true; boolean blockval = true;
ps_checkposition_calls++; ps_checkposition_calls.value.i++;
I_Assert(thing != NULL); I_Assert(thing != NULL);
#ifdef PARANOIA #ifdef PARANOIA

View file

@ -78,7 +78,7 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
// //
// P_SetupStateAnimation // P_SetupStateAnimation
// //
FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st) static void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
{ {
INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin) INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin)
? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1 ? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1
@ -1688,7 +1688,7 @@ static void P_PushableCheckBustables(mobj_t *mo)
if (!(rover->flags & FF_BUSTUP)) if (!(rover->flags & FF_BUSTUP))
continue; continue;
if (!(rover->specialflags & FS_PUSHABLES)) if (!(rover->bustflags & FB_PUSHABLES))
continue; continue;
if (rover->master->frontsector->crumblestate != CRUMBLE_NONE) if (rover->master->frontsector->crumblestate != CRUMBLE_NONE)
@ -1698,7 +1698,7 @@ static void P_PushableCheckBustables(mobj_t *mo)
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
// Height checks // Height checks
if (rover->specialflags & FS_ONLYBOTTOM) if (rover->bustflags & FB_ONLYBOTTOM)
{ {
if (mo->z + mo->momz + mo->height < bottomheight) if (mo->z + mo->momz + mo->height < bottomheight)
continue; continue;
@ -1740,7 +1740,7 @@ static void P_PushableCheckBustables(mobj_t *mo)
EV_CrumbleChain(NULL, rover); // node->m_sector EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor?? // Run a linedef executor??
if (rover->specialflags & FS_EXECUTOR) if (rover->bustflags & FB_EXECUTOR)
P_LinedefExecute(rover->busttag, mo, node->m_sector); P_LinedefExecute(rover->busttag, mo, node->m_sector);
goto bustupdone; goto bustupdone;
@ -3241,8 +3241,8 @@ void P_MobjCheckWater(mobj_t *mobj)
|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player))) || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
continue; continue;
topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y); topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, sector);
bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, sector);
if (mobj->eflags & MFE_VERTICALFLIP) if (mobj->eflags & MFE_VERTICALFLIP)
{ {
@ -6842,7 +6842,7 @@ void P_RunOverlays(void)
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP); mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
mo->scale = mo->destscale = mo->target->scale; mo->scale = mo->destscale = mo->target->scale;
mo->angle = mo->target->angle + mo->movedir; mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir;
if (!(mo->state->frame & FF_ANIMATE)) if (!(mo->state->frame & FF_ANIMATE))
zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale); zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);

View file

@ -3284,8 +3284,6 @@ static void P_ConvertBinaryMap(void)
case 76: //Make FOF bouncy case 76: //Make FOF bouncy
lines[i].args[0] = tag; lines[i].args[0] = tag;
lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; lines[i].args[1] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS;
if (lines[i].flags & ML_BOUNCY)
lines[i].args[2] = 1;
break; break;
case 100: //FOF: solid, opaque, shadowcasting case 100: //FOF: solid, opaque, shadowcasting
case 101: //FOF: solid, opaque, non-shadowcasting case 101: //FOF: solid, opaque, non-shadowcasting

View file

@ -2078,7 +2078,7 @@ void P_SwitchWeather(INT32 weathernum)
continue; // not a precipmobj thinker continue; // not a precipmobj thinker
precipmobj = (precipmobj_t *)think; precipmobj = (precipmobj_t *)think;
if (weathernum == (PRECIP_RAIN || PRECIP_STORM || PRECIP_STORM_NOSTRIKES)) // Snow To Rain if (weathernum == PRECIP_RAIN || weathernum == PRECIP_STORM || weathernum == PRECIP_STORM_NOSTRIKES) // Snow To Rain
{ {
precipmobj->flags = mobjinfo[MT_RAIN].flags; precipmobj->flags = mobjinfo[MT_RAIN].flags;
st = &states[mobjinfo[MT_RAIN].spawnstate]; st = &states[mobjinfo[MT_RAIN].spawnstate];
@ -5903,10 +5903,6 @@ static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline)
rover->flags |= FF_BOUNCY; rover->flags |= FF_BOUNCY;
rover->spawnflags |= FF_BOUNCY; rover->spawnflags |= FF_BOUNCY;
rover->bouncestrength = (paramline->args[1]<< FRACBITS)/100; rover->bouncestrength = (paramline->args[1]<< FRACBITS)/100;
if (paramline->args[2])
rover->specialflags |= FS_DAMPEN;
else
rover->specialflags &= ~FS_DAMPEN;
CheckForBouncySector = true; CheckForBouncySector = true;
break; break;
} }
@ -6536,7 +6532,7 @@ void P_SpawnSpecials(boolean fromnetsave)
case 254: // Bustable block case 254: // Bustable block
{ {
UINT8 busttype = BT_REGULAR; UINT8 busttype = BT_REGULAR;
ffloorspecialflags_e bustflags = 0; ffloorbustflags_e bustflags = 0;
ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP; ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP;
@ -6559,15 +6555,15 @@ void P_SpawnSpecials(boolean fromnetsave)
//Flags //Flags
if (lines[i].args[3] & TMFB_PUSHABLES) if (lines[i].args[3] & TMFB_PUSHABLES)
bustflags |= FS_PUSHABLES; bustflags |= FB_PUSHABLES;
if (lines[i].args[3] & TMFB_EXECUTOR) if (lines[i].args[3] & TMFB_EXECUTOR)
bustflags |= FS_EXECUTOR; bustflags |= FB_EXECUTOR;
if (lines[i].args[3] & TMFB_ONLYBOTTOM) if (lines[i].args[3] & TMFB_ONLYBOTTOM)
bustflags |= FS_ONLYBOTTOM; bustflags |= FB_ONLYBOTTOM;
if (lines[i].args[3] & TMFB_SPLAT) if (lines[i].args[3] & TMFB_SPLAT)
ffloorflags |= FF_SPLAT; ffloorflags |= FF_SPLAT;
if (busttype != BT_TOUCH || bustflags & FS_ONLYBOTTOM) if (busttype != BT_TOUCH || bustflags & FB_ONLYBOTTOM)
ffloorflags |= FF_BLOCKPLAYER; ffloorflags |= FF_BLOCKPLAYER;
TAG_ITER_SECTORS(lines[i].args[0], s) TAG_ITER_SECTORS(lines[i].args[0], s)
@ -6575,8 +6571,8 @@ void P_SpawnSpecials(boolean fromnetsave)
ffloor_t *fflr = P_AddFakeFloor(&sectors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers); ffloor_t *fflr = P_AddFakeFloor(&sectors[s], lines[i].frontsector, lines + i, lines[i].args[1], ffloorflags, secthinkers);
if (!fflr) if (!fflr)
continue; continue;
fflr->bustflags = bustflags;
fflr->busttype = busttype; fflr->busttype = busttype;
fflr->specialflags = bustflags;
fflr->busttag = lines[i].args[4]; fflr->busttag = lines[i].args[4];
} }
break; break;
@ -6636,12 +6632,12 @@ void P_SpawnSpecials(boolean fromnetsave)
} }
if (lines[i].args[3] & TMFB_ONLYBOTTOM) if (lines[i].args[3] & TMFB_ONLYBOTTOM)
fflr->specialflags |= FS_ONLYBOTTOM; fflr->bustflags |= FB_ONLYBOTTOM;
if (lines[i].flags & ML_EFFECT4) if (lines[i].flags & ML_EFFECT4)
fflr->specialflags |= FS_PUSHABLES; fflr->bustflags |= FB_PUSHABLES;
if (lines[i].flags & ML_EFFECT5) if (lines[i].flags & ML_EFFECT5)
{ {
fflr->specialflags |= FS_EXECUTOR; fflr->bustflags |= FB_EXECUTOR;
fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; fflr->busttag = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS;
} }
} }
@ -6962,7 +6958,7 @@ void P_SpawnSpecials(boolean fromnetsave)
case 74: // Make FOF bustable case 74: // Make FOF bustable
{ {
UINT8 busttype = BT_REGULAR; UINT8 busttype = BT_REGULAR;
ffloorspecialflags_e bustflags = 0; ffloorbustflags_e bustflags = 0;
if (!udmf) if (!udmf)
break; break;
@ -6984,11 +6980,11 @@ void P_SpawnSpecials(boolean fromnetsave)
} }
if (lines[i].args[2] & TMFB_PUSHABLES) if (lines[i].args[2] & TMFB_PUSHABLES)
bustflags |= FS_PUSHABLES; bustflags |= FB_PUSHABLES;
if (lines[i].args[2] & TMFB_EXECUTOR) if (lines[i].args[2] & TMFB_EXECUTOR)
bustflags |= FS_EXECUTOR; bustflags |= FB_EXECUTOR;
if (lines[i].args[2] & TMFB_ONLYBOTTOM) if (lines[i].args[2] & TMFB_ONLYBOTTOM)
bustflags |= FS_ONLYBOTTOM; bustflags |= FB_ONLYBOTTOM;
TAG_ITER_LINES(lines[i].args[0], l) TAG_ITER_LINES(lines[i].args[0], l)
{ {
@ -7006,9 +7002,8 @@ void P_SpawnSpecials(boolean fromnetsave)
rover->flags |= FF_BUSTUP; rover->flags |= FF_BUSTUP;
rover->spawnflags |= FF_BUSTUP; rover->spawnflags |= FF_BUSTUP;
rover->bustflags = bustflags;
rover->busttype = busttype; rover->busttype = busttype;
rover->specialflags &= ~FS_BUSTMASK;
rover->specialflags |= bustflags;
rover->busttag = lines[i].args[3]; rover->busttag = lines[i].args[3];
CheckForBustableBlocks = true; CheckForBustableBlocks = true;
break; break;

View file

@ -329,7 +329,7 @@ static inline void P_RunThinkers(void)
size_t i; size_t i;
for (i = 0; i < NUM_THINKERLISTS; i++) for (i = 0; i < NUM_THINKERLISTS; i++)
{ {
ps_thlist_times[i] = I_GetPreciseTime(); PS_START_TIMING(ps_thlist_times[i]);
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
{ {
#ifdef PARANOIA #ifdef PARANOIA
@ -337,7 +337,7 @@ static inline void P_RunThinkers(void)
#endif #endif
currentthinker->function.acp1(currentthinker); currentthinker->function.acp1(currentthinker);
} }
ps_thlist_times[i] = I_GetPreciseTime() - ps_thlist_times[i]; PS_STOP_TIMING(ps_thlist_times[i]);
} }
} }
@ -493,7 +493,7 @@ static inline void P_DoSpecialStageStuff(void)
continue; continue;
// If in water, deplete timer 6x as fast. // If in water, deplete timer 6x as fast.
if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & SH_PROTECTWATER)) if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & ((players[i].mo->eflags & MFE_TOUCHLAVA) ? SH_PROTECTFIRE : SH_PROTECTWATER)))
players[i].nightstime -= 5; players[i].nightstime -= 5;
if (--players[i].nightstime > 6) if (--players[i].nightstime > 6)
{ {
@ -659,16 +659,16 @@ void P_Ticker(boolean run)
} }
} }
ps_lua_mobjhooks = 0; ps_lua_mobjhooks.value.i = 0;
ps_checkposition_calls = 0; ps_checkposition_calls.value.i = 0;
LUA_HOOK(PreThinkFrame); LUA_HOOK(PreThinkFrame);
ps_playerthink_time = I_GetPreciseTime(); PS_START_TIMING(ps_playerthink_time);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerThink(&players[i]); P_PlayerThink(&players[i]);
ps_playerthink_time = I_GetPreciseTime() - ps_playerthink_time; PS_STOP_TIMING(ps_playerthink_time);
} }
// Keep track of how long they've been playing! // Keep track of how long they've been playing!
@ -683,18 +683,18 @@ void P_Ticker(boolean run)
if (run) if (run)
{ {
ps_thinkertime = I_GetPreciseTime(); PS_START_TIMING(ps_thinkertime);
P_RunThinkers(); P_RunThinkers();
ps_thinkertime = I_GetPreciseTime() - ps_thinkertime; PS_STOP_TIMING(ps_thinkertime);
// Run any "after all the other thinkers" stuff // Run any "after all the other thinkers" stuff
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]); P_PlayerAfterThink(&players[i]);
ps_lua_thinkframe_time = I_GetPreciseTime(); PS_START_TIMING(ps_lua_thinkframe_time);
LUA_HookThinkFrame(); LUA_HookThinkFrame();
ps_lua_thinkframe_time = I_GetPreciseTime() - ps_lua_thinkframe_time; PS_STOP_TIMING(ps_lua_thinkframe_time);
} }
// Run shield positioning // Run shield positioning

View file

@ -777,7 +777,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
UINT8 oldmare, oldmarelap, oldmarebonuslap; UINT8 oldmare, oldmarelap, oldmarebonuslap;
// Bots can't be NiGHTSerized, silly!1 :P // Bots can't be NiGHTSerized, silly!1 :P
if (player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) if (player->bot)
return; return;
if (player->powers[pw_carry] != CR_NIGHTSMODE) if (player->powers[pw_carry] != CR_NIGHTSMODE)
@ -969,9 +969,6 @@ pflags_t P_GetJumpFlags(player_t *player)
// //
boolean P_PlayerInPain(player_t *player) boolean P_PlayerInPain(player_t *player)
{ {
// If the player doesn't have a mobj, it can't be in pain.
if (!player->mo)
return false;
// no silly, sliding isn't pain // no silly, sliding isn't pain
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing])
return true; return true;
@ -1191,9 +1188,9 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
{ {
if (!player) if (!player)
return; return;
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) if (player->bot)
player = player->botleader; player = &players[consoleplayer];
if (!player->mo) if (!player->mo)
return; return;
@ -1237,8 +1234,8 @@ void P_GivePlayerSpheres(player_t *player, INT32 num_spheres)
if (!player) if (!player)
return; return;
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) if (player->bot)
player = player->botleader; player = &players[consoleplayer];
if (!player->mo) if (!player->mo)
return; return;
@ -1264,8 +1261,8 @@ void P_GivePlayerLives(player_t *player, INT32 numlives)
if (!player) if (!player)
return; return;
if ((player->bot == BOT_2PAI || player->bot == BOT_2PHUMAN) && player->botleader) if (player->bot)
player = player->botleader; player = &players[consoleplayer];
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ {
@ -2659,7 +2656,7 @@ static void P_CheckBustableBlocks(player_t *player)
} }
// Height checks // Height checks
if (rover->specialflags & FS_ONLYBOTTOM) if (rover->bustflags & FB_ONLYBOTTOM)
{ {
if (player->mo->z + player->mo->momz + player->mo->height < bottomheight) if (player->mo->z + player->mo->momz + player->mo->height < bottomheight)
continue; continue;
@ -2713,7 +2710,7 @@ static void P_CheckBustableBlocks(player_t *player)
EV_CrumbleChain(NULL, rover); // node->m_sector EV_CrumbleChain(NULL, rover); // node->m_sector
// Run a linedef executor?? // Run a linedef executor??
if (rover->specialflags & FS_EXECUTOR) if (rover->bustflags & FB_EXECUTOR)
P_LinedefExecute(rover->busttag, player->mo, node->m_sector); P_LinedefExecute(rover->busttag, player->mo, node->m_sector);
goto bustupdone; goto bustupdone;
@ -2769,10 +2766,6 @@ static void P_CheckBouncySectors(player_t *player)
{ {
rover->flags |= FF_BOUNCY; rover->flags |= FF_BOUNCY;
rover->bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100; rover->bouncestrength = P_AproxDistance(rover->master->dx, rover->master->dy)/100;
if (rover->master->flags & ML_BOUNCY)
rover->specialflags |= FS_DAMPEN;
else
rover->specialflags &= ~FS_DAMPEN;
} }
if (!(rover->flags & FF_BOUNCY)) if (!(rover->flags & FF_BOUNCY))
@ -2792,17 +2785,9 @@ static void P_CheckBouncySectors(player_t *player)
{ {
player->mo->momx = -FixedMul(player->mo->momx,rover->bouncestrength); player->mo->momx = -FixedMul(player->mo->momx,rover->bouncestrength);
player->mo->momy = -FixedMul(player->mo->momy,rover->bouncestrength); player->mo->momy = -FixedMul(player->mo->momy,rover->bouncestrength);
if (player->pflags & PF_SPINNING)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
player->pflags |= PF_THOKKED;
}
} }
else else
{ {
fixed_t newmom;
pslope_t *slope = (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) ? *rover->t_slope : *rover->b_slope; pslope_t *slope = (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) ? *rover->t_slope : *rover->b_slope;
momentum.x = player->mo->momx; momentum.x = player->mo->momx;
@ -2812,53 +2797,28 @@ static void P_CheckBouncySectors(player_t *player)
if (slope) if (slope)
P_ReverseQuantizeMomentumToSlope(&momentum, slope); P_ReverseQuantizeMomentumToSlope(&momentum, slope);
newmom = momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2; momentum.z = -FixedMul(momentum.z,rover->bouncestrength)/2;
if (abs(newmom) < (rover->bouncestrength*2)) if (abs(momentum.z) < (rover->bouncestrength*2))
goto bouncydone; goto bouncydone;
if (!(rover->specialflags & FS_DAMPEN)) if (momentum.z > FixedMul(24*FRACUNIT, player->mo->scale)) //half of the default player height
{ momentum.z = FixedMul(24*FRACUNIT, player->mo->scale);
if (newmom > 0) else if (momentum.z < -FixedMul(24*FRACUNIT, player->mo->scale))
{ momentum.z = -FixedMul(24*FRACUNIT, player->mo->scale);
if (newmom < 8*FRACUNIT)
newmom = 8*FRACUNIT;
}
else if (newmom < 0)
{
if (newmom > -8*FRACUNIT)
newmom = -8*FRACUNIT;
}
}
if (newmom > P_GetPlayerHeight(player)/2)
newmom = P_GetPlayerHeight(player)/2;
else if (newmom < -P_GetPlayerHeight(player)/2)
newmom = -P_GetPlayerHeight(player)/2;
momentum.z = newmom*2;
if (slope) if (slope)
P_QuantizeMomentumToSlope(&momentum, slope); P_QuantizeMomentumToSlope(&momentum, slope);
player->mo->momx = momentum.x; player->mo->momx = momentum.x;
player->mo->momy = momentum.y; player->mo->momy = momentum.y;
player->mo->momz = momentum.z/2; player->mo->momz = momentum.z;
if (player->pflags & PF_SPINNING) if (player->pflags & PF_SPINNING)
{ {
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
player->pflags |= PF_THOKKED; player->pflags |= PF_THOKKED;
} }
} }
if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<<FRACBITS, player->mo->scale) && player->mo->momz)
{
player->pflags &= ~PF_SPINNING;
player->pflags |= P_GetJumpFlags(player);
}
goto bouncydone; goto bouncydone;
} }
} }

View file

@ -808,7 +808,7 @@ static void R_AddPolyObjects(subsector_t *sub)
} }
// for render stats // for render stats
ps_numpolyobjects += numpolys; ps_numpolyobjects.value.i += numpolys;
// sort polyobjects // sort polyobjects
R_SortPolyObjects(sub); R_SortPolyObjects(sub);
@ -1243,7 +1243,7 @@ void R_RenderBSPNode(INT32 bspnum)
node_t *bsp; node_t *bsp;
INT32 side; INT32 side;
ps_numbspcalls++; ps_numbspcalls.value.i++;
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{ {

View file

@ -154,12 +154,10 @@ typedef enum
typedef enum typedef enum
{ {
FS_PUSHABLES = 0x1, // FF_BUSTABLE: Bustable by pushables FB_PUSHABLES = 0x1, // Bustable by pushables
FS_EXECUTOR = 0x2, // FF_BUSTABLE: Trigger linedef executor FB_EXECUTOR = 0x2, // Trigger linedef executor
FS_ONLYBOTTOM = 0x4, // FF_BUSTABLE: Only bustable from below FB_ONLYBOTTOM = 0x4, // Only bustable from below
FS_BUSTMASK = 0x7, } ffloorbustflags_e;
FS_DAMPEN = 0x8, // FF_BOUNCY: Dampen bounce
} ffloorspecialflags_e;
typedef enum typedef enum
{ {
@ -201,10 +199,8 @@ typedef struct ffloor_s
INT32 alpha; INT32 alpha;
tic_t norender; // for culling tic_t norender; // for culling
// Flags that are only relevant for special ffloor types
ffloorspecialflags_e specialflags;
// Only relevant for FF_BUSTUP // Only relevant for FF_BUSTUP
ffloorbustflags_e bustflags;
UINT8 busttype; UINT8 busttype;
INT16 busttag; INT16 busttag;

View file

@ -666,7 +666,6 @@ void R_DrawTiltedSplat_NPO2_8(void)
for (; width != 0; width--) for (; width != 0; width--)
{ {
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)];
// Lactozilla: Non-powers-of-two // Lactozilla: Non-powers-of-two
{ {
fixed_t x = (((fixed_t)u) >> FRACBITS); fixed_t x = (((fixed_t)u) >> FRACBITS);

View file

@ -101,21 +101,22 @@ extracolormap_t *extra_colormaps = NULL;
// Render stats // Render stats
precise_t ps_prevframetime = 0; precise_t ps_prevframetime = 0;
precise_t ps_rendercalltime = 0; ps_metric_t ps_rendercalltime = {0};
precise_t ps_uitime = 0; ps_metric_t ps_otherrendertime = {0};
precise_t ps_swaptime = 0; ps_metric_t ps_uitime = {0};
ps_metric_t ps_swaptime = {0};
precise_t ps_bsptime = 0; ps_metric_t ps_bsptime = {0};
precise_t ps_sw_spritecliptime = 0; ps_metric_t ps_sw_spritecliptime = {0};
precise_t ps_sw_portaltime = 0; ps_metric_t ps_sw_portaltime = {0};
precise_t ps_sw_planetime = 0; ps_metric_t ps_sw_planetime = {0};
precise_t ps_sw_maskedtime = 0; ps_metric_t ps_sw_maskedtime = {0};
int ps_numbspcalls = 0; ps_metric_t ps_numbspcalls = {0};
int ps_numsprites = 0; ps_metric_t ps_numsprites = {0};
int ps_numdrawnodes = 0; ps_metric_t ps_numdrawnodes = {0};
int ps_numpolyobjects = 0; ps_metric_t ps_numpolyobjects = {0};
static CV_PossibleValue_t drawdist_cons_t[] = { static CV_PossibleValue_t drawdist_cons_t[] = {
{256, "256"}, {512, "512"}, {768, "768"}, {256, "256"}, {512, "512"}, {768, "768"},
@ -1496,11 +1497,11 @@ void R_RenderPlayerView(player_t *player)
mytotal = 0; mytotal = 0;
ProfZeroTimer(); ProfZeroTimer();
#endif #endif
ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0; ps_numbspcalls.value.i = ps_numpolyobjects.value.i = ps_numdrawnodes.value.i = 0;
ps_bsptime = I_GetPreciseTime(); PS_START_TIMING(ps_bsptime);
R_RenderBSPNode((INT32)numnodes - 1); R_RenderBSPNode((INT32)numnodes - 1);
ps_bsptime = I_GetPreciseTime() - ps_bsptime; PS_STOP_TIMING(ps_bsptime);
ps_numsprites = visspritecount; ps_numsprites.value.i = visspritecount;
#ifdef TIMING #ifdef TIMING
RDMSR(0x10, &mycount); RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add mytotal += mycount; // 64bit add
@ -1510,9 +1511,9 @@ void R_RenderPlayerView(player_t *player)
//profile stuff --------------------------------------------------------- //profile stuff ---------------------------------------------------------
Mask_Post(&masks[nummasks - 1]); Mask_Post(&masks[nummasks - 1]);
ps_sw_spritecliptime = I_GetPreciseTime(); PS_START_TIMING(ps_sw_spritecliptime);
R_ClipSprites(drawsegs, NULL); R_ClipSprites(drawsegs, NULL);
ps_sw_spritecliptime = I_GetPreciseTime() - ps_sw_spritecliptime; PS_STOP_TIMING(ps_sw_spritecliptime);
// Add skybox portals caused by sky visplanes. // Add skybox portals caused by sky visplanes.
@ -1520,7 +1521,7 @@ void R_RenderPlayerView(player_t *player)
Portal_AddSkyboxPortals(); Portal_AddSkyboxPortals();
// Portal rendering. Hijacks the BSP traversal. // Portal rendering. Hijacks the BSP traversal.
ps_sw_portaltime = I_GetPreciseTime(); PS_START_TIMING(ps_sw_portaltime);
if (portal_base) if (portal_base)
{ {
portal_t *portal; portal_t *portal;
@ -1560,17 +1561,17 @@ void R_RenderPlayerView(player_t *player)
Portal_Remove(portal); Portal_Remove(portal);
} }
} }
ps_sw_portaltime = I_GetPreciseTime() - ps_sw_portaltime; PS_STOP_TIMING(ps_sw_portaltime);
ps_sw_planetime = I_GetPreciseTime(); PS_START_TIMING(ps_sw_planetime);
R_DrawPlanes(); R_DrawPlanes();
ps_sw_planetime = I_GetPreciseTime() - ps_sw_planetime; PS_STOP_TIMING(ps_sw_planetime);
// draw mid texture and sprite // draw mid texture and sprite
// And now 3D floors/sides! // And now 3D floors/sides!
ps_sw_maskedtime = I_GetPreciseTime(); PS_START_TIMING(ps_sw_maskedtime);
R_DrawMasked(masks, nummasks); R_DrawMasked(masks, nummasks);
ps_sw_maskedtime = I_GetPreciseTime() - ps_sw_maskedtime; PS_STOP_TIMING(ps_sw_maskedtime);
free(masks); free(masks);
} }

View file

@ -17,6 +17,7 @@
#include "d_player.h" #include "d_player.h"
#include "r_data.h" #include "r_data.h"
#include "r_textures.h" #include "r_textures.h"
#include "m_perfstats.h" // ps_metric_t
// //
// POV related. // POV related.
@ -79,21 +80,22 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
// Render stats // Render stats
extern precise_t ps_prevframetime;// time when previous frame was rendered extern precise_t ps_prevframetime;// time when previous frame was rendered
extern precise_t ps_rendercalltime; extern ps_metric_t ps_rendercalltime;
extern precise_t ps_uitime; extern ps_metric_t ps_otherrendertime;
extern precise_t ps_swaptime; extern ps_metric_t ps_uitime;
extern ps_metric_t ps_swaptime;
extern precise_t ps_bsptime; extern ps_metric_t ps_bsptime;
extern precise_t ps_sw_spritecliptime; extern ps_metric_t ps_sw_spritecliptime;
extern precise_t ps_sw_portaltime; extern ps_metric_t ps_sw_portaltime;
extern precise_t ps_sw_planetime; extern ps_metric_t ps_sw_planetime;
extern precise_t ps_sw_maskedtime; extern ps_metric_t ps_sw_maskedtime;
extern int ps_numbspcalls; extern ps_metric_t ps_numbspcalls;
extern int ps_numsprites; extern ps_metric_t ps_numsprites;
extern int ps_numdrawnodes; extern ps_metric_t ps_numdrawnodes;
extern int ps_numpolyobjects; extern ps_metric_t ps_numpolyobjects;
// //
// REFRESH - the actual rendering functions. // REFRESH - the actual rendering functions.

View file

@ -227,8 +227,8 @@ void RotatedPatch_DoRotation(rotsprite_t *rotsprite, patch_t *patch, INT32 angle
ox = (newwidth / 2) + (leftoffset - xpivot); ox = (newwidth / 2) + (leftoffset - xpivot);
oy = (newheight / 2) + (patch->topoffset - ypivot); oy = (newheight / 2) + (patch->topoffset - ypivot);
width = (maxx - minx); width = (maxx+1 - minx);
height = (maxy - miny); height = (maxy+1 - miny);
if ((unsigned)(width * height) != size) if ((unsigned)(width * height) != size)
{ {

View file

@ -318,7 +318,7 @@ static visplane_t *new_visplane(unsigned hash)
visplane_t *check = freetail; visplane_t *check = freetail;
if (!check) if (!check)
{ {
check = calloc(2, sizeof (*check)); check = malloc(sizeof (*check));
if (check == NULL) I_Error("%s: Out of memory", "new_visplane"); // FIXME: ugly if (check == NULL) I_Error("%s: Out of memory", "new_visplane"); // FIXME: ugly
} }
else else

View file

@ -2745,7 +2745,7 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link)
node->ffloor = NULL; node->ffloor = NULL;
node->sprite = NULL; node->sprite = NULL;
ps_numdrawnodes++; ps_numdrawnodes.value.i++;
return node; return node;
} }

View file

@ -2163,7 +2163,13 @@ precise_t I_GetPreciseTime(void)
int I_PreciseToMicros(precise_t d) int I_PreciseToMicros(precise_t d)
{ {
return (int)(d / (timer_frequency / 1000000.0)); // d is going to be converted into a double. So remove the highest bits
// to avoid loss of precision in the lower bits, for the (probably rare) case
// that the higher bits are actually used.
d &= ((precise_t)1 << 53) - 1; // The mantissa of a double can handle 53 bits at most.
// The resulting double from the calculation is converted first to UINT64 to avoid overflow,
// which is undefined behaviour when converting floating point values to integers.
return (int)(UINT64)(d / (timer_frequency / 1000000.0));
} }
// //

View file

@ -409,11 +409,6 @@ void I_UpdateMouseGrab(void)
SDLdoGrabMouse(); SDLdoGrabMouse();
} }
boolean I_GetMouseGrab(void)
{
return (boolean)SDL_GetWindowGrab(window);
}
void I_SetMouseGrab(boolean grab) void I_SetMouseGrab(boolean grab)
{ {
if (grab) if (grab)

View file

@ -2037,9 +2037,8 @@ static void ST_drawNiGHTSHUD(void)
else else
numbersize = 48/2; numbersize = 48/2;
if ((oldspecialstage && leveltime & 2) if ((oldspecialstage && leveltime & 2) &&
&& (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(stplyr->powers[pw_shield] & ((stplyr->mo->eflags & MFE_TOUCHLAVA) ? SH_PROTECTFIRE : SH_PROTECTWATER))))
&& !(stplyr->powers[pw_shield] & SH_PROTECTWATER))
col = SKINCOLOR_ORANGE; col = SKINCOLOR_ORANGE;
ST_DrawNightsOverlayNum((160 + numbersize)<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP, realnightstime, nightsnum, col); ST_DrawNightsOverlayNum((160 + numbersize)<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP, realnightstime, nightsnum, col);
@ -2188,7 +2187,7 @@ static void ST_drawMatchHUD(void)
{ {
sprintf(penaltystr, "-%d", stplyr->ammoremoval); sprintf(penaltystr, "-%d", stplyr->ammoremoval);
V_DrawString(offset + 8 + stplyr->ammoremovalweapon * 20, y, V_DrawString(offset + 8 + stplyr->ammoremovalweapon * 20, y,
V_REDMAP|V_SNAPTOBOTTOM, penaltystr); V_REDMAP|V_SNAPTOBOTTOM|V_PERPLAYER, penaltystr);
} }
} }

View file

@ -105,7 +105,7 @@ static UINT16 lumpnumcacheindex = 0;
// GLOBALS // GLOBALS
//=========================================================================== //===========================================================================
UINT16 numwadfiles; // number of active wadfiles UINT16 numwadfiles; // number of active wadfiles
wadfile_t *wadfiles[MAX_WADFILES]; // 0 to numwadfiles-1 are valid wadfile_t **wadfiles; // 0 to numwadfiles-1 are valid
// W_Shutdown // W_Shutdown
// Closes all of the WAD files before quitting // Closes all of the WAD files before quitting
@ -134,6 +134,8 @@ void W_Shutdown(void)
Z_Free(wad->lumpinfo); Z_Free(wad->lumpinfo);
Z_Free(wad); Z_Free(wad);
} }
Z_Free(wadfiles);
} }
//=========================================================================== //===========================================================================
@ -844,7 +846,6 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
#ifndef NOMD5 #ifndef NOMD5
size_t i; size_t i;
#endif #endif
size_t packetsize;
UINT8 md5sum[16]; UINT8 md5sum[16];
int important; int important;
@ -862,9 +863,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
refreshdirname = NULL; refreshdirname = NULL;
//CONS_Debug(DBG_SETUP, "Loading %s\n", filename); //CONS_Debug(DBG_SETUP, "Loading %s\n", filename);
//
// check if limit of active wadfiles // Check if the game reached the limit of active wadfiles.
//
if (numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
{ {
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
@ -884,24 +884,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
return INT16_MAX; return INT16_MAX;
} }
// Check if wad files will overflow fileneededbuffer. Only the filename part important = !important;
// is send in the packet; cf.
// see PutFileNeeded in d_netfil.c
if ((important = !important))
{
packetsize = packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE;
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
{
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
refreshdirmenu |= REFRESHDIR_MAX;
if (handle)
fclose(handle);
return W_InitFileError(filename, startup);
}
packetsizetally = packetsize;
}
#ifndef NOMD5 #ifndef NOMD5
// //
@ -913,11 +896,12 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
for (i = 0; i < numwadfiles; i++) for (i = 0; i < numwadfiles; i++)
{ {
if (wadfiles[i]->type == RET_FOLDER)
continue;
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
{ {
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
if (important)
packetsizetally -= nameonlylength(filename) + FILENEEDEDSIZE;
if (handle) if (handle)
fclose(handle); fclose(handle);
return W_InitFileError(filename, false); return W_InitFileError(filename, false);
@ -984,6 +968,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
// add the wadfile // add the wadfile
// //
CONS_Printf(M_GetText("Added file %s (%u lumps)\n"), filename, numlumps); CONS_Printf(M_GetText("Added file %s (%u lumps)\n"), filename, numlumps);
wadfiles = Z_Realloc(wadfiles, sizeof(wadfile_t) * (numwadfiles + 1), PU_STATIC, NULL);
wadfiles[numwadfiles] = wadfile; wadfiles[numwadfiles] = wadfile;
numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded
@ -1046,22 +1031,7 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
return W_InitFileError(path, startup); return W_InitFileError(path, startup);
} }
important = 0; // ??? important = 0; /// \todo Implement a W_VerifyFolder.
/// \todo Implement a W_VerifyFolder.
if ((important = !important))
{
size_t packetsize = packetsizetally + strlen(path) + FILENEEDEDSIZE;
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
{
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
refreshdirmenu |= REFRESHDIR_MAX;
return W_InitFileError(path, startup);
}
packetsizetally = packetsize;
}
// Remove path delimiters. // Remove path delimiters.
p = path + (strlen(path) - 1); p = path + (strlen(path) - 1);
@ -1132,8 +1102,6 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
if (samepaths(wadfiles[i]->path, fullpath) > 0) if (samepaths(wadfiles[i]->path, fullpath) > 0)
{ {
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), path); CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), path);
if (important)
packetsizetally -= strlen(path) + FILENEEDEDSIZE;
Z_Free(fn); Z_Free(fn);
Z_Free(fullpath); Z_Free(fullpath);
return W_InitFileError(path, false); return W_InitFileError(path, false);
@ -1197,11 +1165,13 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
* *
* \param filenames A null-terminated list of files to use. * \param filenames A null-terminated list of files to use.
*/ */
void W_InitMultipleFiles(char **filenames) void W_InitMultipleFiles(addfilelist_t *list)
{ {
for (; *filenames; filenames++) size_t i = 0;
for (; i < list->numfiles; i++)
{ {
const char *fn = (*filenames); const char *fn = list->files[i];
char pathsep = fn[strlen(fn) - 1]; char pathsep = fn[strlen(fn) - 1];
boolean mainfile = (numwadfiles < mainwads); boolean mainfile = (numwadfiles < mainwads);
@ -1219,7 +1189,7 @@ void W_InitMultipleFiles(char **filenames)
*/ */
static boolean TestValidLump(UINT16 wad, UINT16 lump) static boolean TestValidLump(UINT16 wad, UINT16 lump)
{ {
I_Assert(wad < MAX_WADFILES); I_Assert(wad < numwadfiles);
if (!wadfiles[wad]) // make sure the wad file exists if (!wadfiles[wad]) // make sure the wad file exists
return false; return false;
@ -1636,7 +1606,7 @@ size_t W_LumpLength(lumpnum_t lumpnum)
// //
// W_IsLumpWad // W_IsLumpWad
// Is the lump a WAD? (presumably in a PK3) // Is the lump a WAD? (presumably not in a WAD)
// //
boolean W_IsLumpWad(lumpnum_t lumpnum) boolean W_IsLumpWad(lumpnum_t lumpnum)
{ {
@ -1649,12 +1619,12 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
return !strnicmp(lumpfullName + strlen(lumpfullName) - 4, ".wad", 4); return !strnicmp(lumpfullName + strlen(lumpfullName) - 4, ".wad", 4);
} }
return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned return false; // WADs should never be inside WADs as far as SRB2 is concerned
} }
// //
// W_IsLumpFolder // W_IsLumpFolder
// Is the lump a folder? (in a PK3 obviously) // Is the lump a folder? (not in a WAD obviously)
// //
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump) boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
{ {
@ -1665,7 +1635,7 @@ boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
return (name[strlen(name)-1] == '/'); // folders end in '/' return (name[strlen(name)-1] == '/'); // folders end in '/'
} }
return false; // non-PK3s don't have folders return false; // WADs don't have folders
} }
#ifdef HAVE_ZLIB #ifdef HAVE_ZLIB
@ -2217,7 +2187,7 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5)
#else #else
I_Error I_Error
#endif #endif
(M_GetText("File is old, is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); (M_GetText("File is old, is corrupt or has been modified:\n%s\nFound MD5: %s\nWanted MD5: %s\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5);
} }
#endif #endif
} }

View file

@ -97,9 +97,15 @@ virtlump_t* vres_Find(const virtres_t*, const char*);
// DYNAMIC WAD LOADING // DYNAMIC WAD LOADING
// ========================================================================= // =========================================================================
// Maximum of files that can be loaded
// (there is a max of simultaneous open files anyway)
#ifdef ENFORCE_WAD_LIMIT
#define MAX_WADFILES 2048 // This cannot be any higher than UINT16_MAX.
#else
#define MAX_WADFILES UINT16_MAX
#endif
#define MAX_WADPATH 512 #define MAX_WADPATH 512
#define MAX_WADFILES 48 // maximum of wad files used at the same time
// (there is a max of simultaneous open files anyway, and this should be plenty)
#define lumpcache_t void * #define lumpcache_t void *
@ -134,7 +140,13 @@ typedef struct wadfile_s
#define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad #define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad
extern UINT16 numwadfiles; extern UINT16 numwadfiles;
extern wadfile_t *wadfiles[MAX_WADFILES]; extern wadfile_t **wadfiles;
typedef struct
{
char **files;
size_t numfiles;
} addfilelist_t;
// ========================================================================= // =========================================================================
@ -148,7 +160,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup);
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup); UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup);
// W_InitMultipleFiles exits if a file was not found, but not if all is okay. // W_InitMultipleFiles exits if a file was not found, but not if all is okay.
void W_InitMultipleFiles(char **filenames); void W_InitMultipleFiles(addfilelist_t *list);
#define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3 || (wadfile)->type == RET_FOLDER) #define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3 || (wadfile)->type == RET_FOLDER)

View file

@ -239,12 +239,12 @@ void Y_LoadIntermissionData(void)
} }
data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH); data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_PATCH);
// get background patches
bgpatch = W_CachePatchName("INTERSCR", PU_PATCH);
// grab an interscreen if appropriate // grab an interscreen if appropriate
if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') if (mapheaderinfo[gamemap-1]->interscreen[0] != '#')
interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH);
else // no interscreen? use default background
bgpatch = W_CachePatchName("INTERSCR", PU_PATCH);
break; break;
} }
case int_spec: case int_spec:
@ -255,12 +255,11 @@ void Y_LoadIntermissionData(void)
data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH); data.spec.pscore = W_CachePatchName("YB_SCORE", PU_PATCH);
data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH); data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_PATCH);
// get background tile
bgtile = W_CachePatchName("SPECTILE", PU_PATCH);
// grab an interscreen if appropriate // grab an interscreen if appropriate
if (mapheaderinfo[gamemap-1]->interscreen[0] != '#') if (mapheaderinfo[gamemap-1]->interscreen[0] != '#')
interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH); interpic = W_CachePatchName(mapheaderinfo[gamemap-1]->interscreen, PU_PATCH);
else // no interscreen? use default background
bgtile = W_CachePatchName("SPECTILE", PU_PATCH);
break; break;
} }
case int_ctf: case int_ctf:

View file

@ -39,6 +39,7 @@ enum
// Tags < PU_LEVEL are not purged until freed explicitly. // Tags < PU_LEVEL are not purged until freed explicitly.
PU_STATIC = 1, // static entire execution time PU_STATIC = 1, // static entire execution time
PU_LUA = 2, // static entire execution time -- used by lua so it doesn't get caught in loops forever PU_LUA = 2, // static entire execution time -- used by lua so it doesn't get caught in loops forever
PU_PERFSTATS = 3, // static between changes to ps_samplesize cvar
PU_SOUND = 11, // static while playing PU_SOUND = 11, // static while playing
PU_MUSIC = 12, // static while playing PU_MUSIC = 12, // static while playing