Commit 5e890ee6 by Jaime Ita Passos

Merge branch 'next' into spritestuff2

parents a655257f 85c5fa95
......@@ -32,6 +32,7 @@ set(SRB2_CORE_SOURCES
m_fixed.c
m_menu.c
m_misc.c
m_perfstats.c
m_queue.c
m_random.c
md5.c
......@@ -97,6 +98,7 @@ set(SRB2_CORE_HEADERS
m_fixed.h
m_menu.h
m_misc.h
m_perfstats.h
m_queue.h
m_random.h
m_swap.h
......@@ -171,6 +173,7 @@ set(SRB2_CORE_GAME_SOURCES
p_telept.c
p_tick.c
p_user.c
taglist.c
p_local.h
p_maputl.h
......@@ -182,6 +185,7 @@ set(SRB2_CORE_GAME_SOURCES
p_slopes.h
p_spec.h
p_tick.h
taglist.h
)
if(NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
......@@ -234,7 +238,9 @@ set(SRB2_CONFIG_HAVE_GME ON CACHE BOOL
set(SRB2_CONFIG_HAVE_OPENMPT ON CACHE BOOL
"Enable OpenMPT support.")
set(SRB2_CONFIG_HAVE_CURL ON CACHE BOOL
"Enable curl support, used for downloading files via HTTP.")
"Enable curl support.")
set(SRB2_CONFIG_HAVE_THREADS ON CACHE BOOL
"Enable multithreading support.")
if(${CMAKE_SYSTEM} MATCHES Windows)
set(SRB2_CONFIG_HAVE_MIXERX ON CACHE BOOL
"Enable SDL Mixer X support.")
......@@ -267,6 +273,7 @@ set(SRB2_LUA_SOURCES
lua_mathlib.c
lua_mobjlib.c
lua_playerlib.c
lua_polyobjlib.c
lua_script.c
lua_skinlib.c
lua_thinkerlib.c
......@@ -457,7 +464,7 @@ endif()
if(${SRB2_CONFIG_HAVE_CURL})
if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES})
set(CURL_FOUND ON)
set(CURL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/curl)
set(CURL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/libs/curl/include)
if(${SRB2_SYSTEM_BITS} EQUAL 64)
set(CURL_LIBRARIES "-L${CMAKE_SOURCE_DIR}/libs/curl/lib64 -lcurl")
else() # 32-bit
......@@ -474,6 +481,12 @@ if(${SRB2_CONFIG_HAVE_CURL})
endif()
endif()
if(${SRB2_CONFIG_HAVE_THREADS})
set(SRB2_HAVE_THREADS ON)
set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/i_threads.h)
add_definitions(-DHAVE_THREADS)
endif()
if(${SRB2_CONFIG_HWRENDER})
add_definitions(-DHWRENDER)
set(SRB2_HWRENDER_SOURCES
......@@ -545,6 +558,7 @@ if(${SRB2_CONFIG_USEASM})
endif()
set(SRB2_USEASM ON)
add_definitions(-DUSEASM)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse3 -mfpmath=sse")
else()
set(SRB2_USEASM OFF)
add_definitions(-DNONX86 -DNORUSEASM)
......
......@@ -277,7 +277,7 @@ OPTS += -DCOMPVERSION
ifndef NONX86
ifndef GCC29
ARCHOPTS?=-march=pentium
ARCHOPTS?=-msse3 -mfpmath=sse
else
ARCHOPTS?=-mpentium
endif
......@@ -486,6 +486,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/m_fixed.o \
$(OBJDIR)/m_menu.o \
$(OBJDIR)/m_misc.o \
$(OBJDIR)/m_perfstats.o \
$(OBJDIR)/m_random.o \
$(OBJDIR)/m_queue.o \
$(OBJDIR)/info.o \
......@@ -523,6 +524,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/r_picformats.o \
$(OBJDIR)/r_portal.o \
$(OBJDIR)/screen.o \
$(OBJDIR)/taglist.o \
$(OBJDIR)/v_video.o \
$(OBJDIR)/s_sound.o \
$(OBJDIR)/sounds.o \
......@@ -608,8 +610,9 @@ ifndef VALGRIND
ifndef NOOBJDUMP
@echo Dumping debugging info
$(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(EXENAME) > $(BIN)/$(DBGNAME).txt
ifdef WINDOWSHELL
-$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
ifndef WINDOWSHELL
else
-$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
endif
endif
......@@ -629,8 +632,9 @@ endif
reobjdump:
@echo Redumping debugging info
$(OBJDUMP) $(OBJDUMP_OPTS) $(BIN)/$(DBGNAME) > $(BIN)/$(DBGNAME).txt
ifdef WINDOWSHELL
-$(GZIP) $(GZIP_OPTS) $(BIN)/$(DBGNAME).txt
ifndef WINDOWSHELL
else
-$(GZIP) $(GZIP_OPT2) $(BIN)/$(DBGNAME).txt
endif
......
......@@ -47,5 +47,6 @@ OBJS:=$(OBJS) \
$(OBJDIR)/lua_skinlib.o \
$(OBJDIR)/lua_thinkerlib.o \
$(OBJDIR)/lua_maplib.o \
$(OBJDIR)/lua_polyobjlib.o \
$(OBJDIR)/lua_blockmaplib.o \
$(OBJDIR)/lua_hudlib.o
......@@ -165,6 +165,8 @@ void COM_BufAddTextEx(const char *ptext, int flags)
*/
void COM_BufInsertTextEx(const char *ptext, int flags)
{
const INT32 old_wait = com_wait;
char *temp = NULL;
size_t templen;
......@@ -176,10 +178,14 @@ void COM_BufInsertTextEx(const char *ptext, int flags)
VS_Clear(&com_text);
}
com_wait = 0;
// add the entire text of the file (or alias)
COM_BufAddTextEx(ptext, flags);
COM_BufExecute(); // do it right away
com_wait += old_wait;
// add the copied off data
if (templen)
{
......@@ -901,6 +907,9 @@ static void COM_Help_f(void)
CONS_Printf(" Current value: %s\n", cvar->string);
else
CONS_Printf(" Current value: %d\n", cvar->value);
if (cvar->revert.v.string != NULL && strcmp(cvar->revert.v.string, cvar->string) != 0)
CONS_Printf(" Value before netgame: %s\n", cvar->revert.v.string);
}
else
{
......@@ -1306,6 +1315,7 @@ void CV_RegisterVar(consvar_t *variable)
consvar_vars = variable;
}
variable->string = variable->zstring = NULL;
memset(&variable->revert, 0, sizeof variable->revert);
variable->changed = 0; // new variable has not been modified by the user
#ifdef PARANOIA
......@@ -1418,6 +1428,18 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
for (i = MAXVAL+1; var->PossibleValue[i].strvalue; i++)
if (v == var->PossibleValue[i].value || !stricmp(var->PossibleValue[i].strvalue, valstr))
{
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.const_munge = var->PossibleValue[i].strvalue;
return;
}
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
......@@ -1478,12 +1500,36 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
// ...or not.
goto badinput;
found:
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.const_munge = var->PossibleValue[i].strvalue;
return;
}
var->value = var->PossibleValue[i].value;
var->string = var->PossibleValue[i].strvalue;
goto finish;
}
}
if (client && execversion_enabled)
{
if (var->revert.allocated)
{
Z_Free(var->revert.v.string);
}
var->revert.v.string = Z_StrDup(valstr);
return;
}
// free the old value string
Z_Free(var->zstring);
......@@ -1702,8 +1748,19 @@ static void CV_LoadVars(UINT8 **p,
serverloading = true;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->flags & CV_NETVAR)
{
if (client && cvar->revert.v.string == NULL)
{
cvar->revert.v.const_munge = cvar->string;
cvar->revert.allocated = ( cvar->zstring != NULL );
cvar->zstring = NULL;/* don't free this */
}
Setvalue(cvar, cvar->defaultvalue, true);
}
}
count = READUINT16(*p);
while (count--)
......@@ -1717,6 +1774,26 @@ static void CV_LoadVars(UINT8 **p,
serverloading = false;
}
void CV_RevertNetVars(void)
{
consvar_t * cvar;
for (cvar = consvar_vars; cvar; cvar = cvar->next)
{
if (cvar->revert.v.string != NULL)
{
Setvalue(cvar, cvar->revert.v.string, false);
if (cvar->revert.allocated)
{
Z_Free(cvar->revert.v.string);
}
cvar->revert.v.string = NULL;
}
}
}
void CV_LoadNetVars(UINT8 **p)
{
CV_LoadVars(p, ReadNetVar);
......@@ -1790,6 +1867,14 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth)
// send the value of the variable
UINT8 buf[128];
UINT8 *p = buf;
// Loading from a config in a netgame? Set revert value.
if (client && execversion_enabled)
{
Setvalue(var, value, true);
return;
}
if (!(server || (addedtogame && IsPlayerAdmin(consoleplayer))))
{
CONS_Printf(M_GetText("Only the server or admin can change: %s %s\n"), var->name, var->string);
......@@ -2323,18 +2408,43 @@ void CV_SaveVariables(FILE *f)
{
char stringtowrite[MAXTEXTCMD+1];
// Silly hack for Min/Max vars
if (!strcmp(cvar->string, "MAX") || !strcmp(cvar->string, "MIN"))
const char * string;
if (cvar->revert.v.string != NULL)
{
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(cvar->value));
else
sprintf(stringtowrite, "%d", cvar->value);
string = cvar->revert.v.string;
}
else
strcpy(stringtowrite, cvar->string);
{
string = cvar->string;
}
// Silly hack for Min/Max vars
#define MINVAL 0
#define MAXVAL 1
if (
cvar->PossibleValue != NULL &&
cvar->PossibleValue[0].strvalue &&
stricmp(cvar->PossibleValue[0].strvalue, "MIN") == 0
){ // bounded cvar
int which = stricmp(string, "MAX") == 0;
if (which || stricmp(string, "MIN") == 0)
{
INT32 value = cvar->PossibleValue[which].value;
if (cvar->flags & CV_FLOAT)
sprintf(stringtowrite, "%f", FIXED_TO_FLOAT(value));
else
sprintf(stringtowrite, "%d", value);
string = stringtowrite;
}
}
#undef MINVAL
#undef MAXVAL
fprintf(f, "%s \"%s\"\n", cvar->name, stringtowrite);
fprintf(f, "%s \"%s\"\n", cvar->name, string);
}
}
......
......@@ -140,6 +140,16 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL
const char *string; // value in string
char *zstring; // Either NULL or same as string.
// If non-NULL, must be Z_Free'd later.
struct
{
char allocated; // whether to Z_Free
union
{
char * string;
const char * const_munge;
} v;
} revert; // value of netvar before joining netgame
UINT16 netid; // used internaly : netid for send end receive
// used only with CV_NETVAR
char changed; // has variable been changed by the user? 0 = no, 1 = yes
......@@ -148,7 +158,7 @@ typedef struct consvar_s //NULL, NULL, 0, NULL, NULL |, 0, NULL, NULL, 0, 0, NUL
/* name, defaultvalue, flags, PossibleValue, func */
#define CVAR_INIT( ... ) \
{ __VA_ARGS__, 0, NULL, NULL, 0U, (char)0, NULL }
{ __VA_ARGS__, 0, NULL, NULL, {0}, 0U, (char)0, NULL }
#ifdef OLD22DEMOCOMPAT
typedef struct old_demo_var old_demo_var_t;
......@@ -208,6 +218,9 @@ void CV_SaveVars(UINT8 **p, boolean in_demo);
#define CV_SaveNetVars(p) CV_SaveVars(p, false)
void CV_LoadNetVars(UINT8 **p);
// then revert after leaving a netgame
void CV_RevertNetVars(void);
#define CV_SaveDemoVars(p) CV_SaveVars(p, true)
void CV_LoadDemoVars(UINT8 **p);
......
......@@ -64,8 +64,10 @@ typedef enum
PT_REQUESTFILE, // Client requests a file transfer
PT_ASKINFOVIAMS, // Packet from the MS requesting info be sent to new client.
// If this ID changes, update masterserver definition.
PT_RESYNCHEND, // Player is now resynched and is being requested to remake the gametic
PT_RESYNCHGET, // Player got resynch packet
PT_WILLRESENDGAMESTATE, // Hey Client, I am about to resend you the gamestate!
PT_CANRECEIVEGAMESTATE, // Okay Server, I'm ready to receive it, you can go ahead.
PT_RECEIVEDGAMESTATE, // Thank you Server, I am ready to play again!
PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file
PT_ASKLUAFILE, // Client telling the server they don't have the file
......@@ -85,8 +87,6 @@ typedef enum
PT_TEXTCMD2, // Splitscreen text commands.
PT_CLIENTJOIN, // Client wants to join; used in start game.
PT_NODETIMEOUT, // Packet sent to self if the connection times out.
PT_RESYNCHING, // Packet sent to resync players.
// Blocks game advance until synched.
PT_LOGIN, // Login attempt from the client.
......@@ -139,176 +139,6 @@ typedef struct
ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
} ATTRPACK servertics_pak;
// Sent to client when all consistency data
// for players has been restored
typedef struct
{
UINT32 randomseed;
// CTF flag stuff
SINT8 flagplayer[2];
INT32 flagloose[2];
INT32 flagflags[2];
fixed_t flagx[2];
fixed_t flagy[2];
fixed_t flagz[2];
UINT32 ingame; // Spectator bit for each player
UINT32 outofcoop; // outofcoop bit for each player
INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
// Resynch game scores and the like all at once
UINT32 score[MAXPLAYERS]; // Everyone's score
INT16 numboxes[MAXPLAYERS];
INT16 totalring[MAXPLAYERS];
tic_t realtime[MAXPLAYERS];
UINT8 laps[MAXPLAYERS];
} ATTRPACK resynchend_pak;
typedef struct
{
// Player stuff
UINT8 playernum;
// Do not send anything visual related.
// Only send data that we need to know for physics.
UINT8 playerstate; // playerstate_t
UINT32 pflags; // pflags_t
UINT8 panim; // panim_t
INT16 angleturn;
INT16 oldrelangleturn;
angle_t aiming;
INT32 currentweapon;
INT32 ringweapons;
UINT16 ammoremoval;
tic_t ammoremovaltimer;
INT32 ammoremovalweapon;
UINT16 powers[NUMPOWERS];
// Score is resynched in the confirm resync packet
INT16 rings;
INT16 spheres;
SINT8 lives;
SINT8 continues;
UINT8 scoreadd;
SINT8 xtralife;
SINT8 pity;
UINT16 skincolor;
INT32 skin;
UINT32 availabilities;
// Just in case Lua does something like
// modify these at runtime
fixed_t camerascale;
fixed_t shieldscale;
fixed_t normalspeed;
fixed_t runspeed;
UINT8 thrustfactor;
UINT8 accelstart;
UINT8 acceleration;
UINT8 charability;
UINT8 charability2;
UINT32 charflags;
UINT32 thokitem; // mobjtype_t
UINT32 spinitem; // mobjtype_t
UINT32 revitem; // mobjtype_t
UINT32 followitem; // mobjtype_t
fixed_t actionspd;
fixed_t mindash;
fixed_t maxdash;
fixed_t jumpfactor;
fixed_t playerheight;
fixed_t playerspinheight;
fixed_t speed;
UINT8 secondjump;
UINT8 fly1;
tic_t glidetime;
UINT8 climbing;
INT32 deadtimer;
tic_t exiting;
UINT8 homing;
tic_t dashmode;
tic_t skidtime;
fixed_t cmomx;
fixed_t cmomy;
fixed_t rmomx;
fixed_t rmomy;
INT32 weapondelay;
INT32 tossdelay;
INT16 starpostx;
INT16 starposty;
INT16 starpostz;
INT32 starpostnum;
tic_t starposttime;
angle_t starpostangle;
fixed_t starpostscale;
INT32 maxlink;
fixed_t dashspeed;
angle_t angle_pos;
angle_t old_angle_pos;
tic_t bumpertime;
INT32 flyangle;
tic_t drilltimer;
INT32 linkcount;
tic_t linktimer;
INT32 anotherflyangle;
tic_t nightstime;
INT32 drillmeter;
UINT8 drilldelay;
UINT8 bonustime;
UINT8 mare;
INT16 lastsidehit, lastlinehit;
tic_t losstime;
UINT8 timeshit;
INT32 onconveyor;
//player->mo stuff
UINT8 hasmo; // Boolean
INT32 health;
angle_t angle;
angle_t rollangle;
fixed_t x;
fixed_t y;
fixed_t z;
fixed_t momx;
fixed_t momy;
fixed_t momz;
fixed_t friction;
fixed_t movefactor;
spritenum_t sprite;
UINT32 frame;
UINT8 sprite2;
UINT16 anim_duration;
fixed_t spritexscale;
fixed_t spriteyscale;
fixed_t spritexoffset;
fixed_t spriteyoffset;
INT32 tics;
statenum_t statenum;
UINT32 flags;
UINT32 flags2;
UINT16 eflags;
UINT32 renderflags;
INT32 blendmode;
fixed_t radius;
fixed_t height;
fixed_t scale;
fixed_t destscale;
fixed_t scalespeed;
} ATTRPACK resynch_pak;
typedef struct
{
UINT8 version; // Different versions don't work
......@@ -322,18 +152,10 @@ typedef struct
UINT8 clientnode;
UINT8 gamestate;
// 0xFF == not in game; else player skin num
UINT8 playerskins[MAXPLAYERS];
UINT16 playercolor[MAXPLAYERS];
UINT32 playeravailabilities[MAXPLAYERS];
UINT8 gametype;
UINT8 modifiedgame;
SINT8 adminplayers[MAXPLAYERS]; // Needs to be signed
char server_context[8]; // Unique context id, generated at server startup.
UINT8 varlengthinputs[0]; // Playernames and netvars
} ATTRPACK serverconfig_pak;
typedef struct
......@@ -470,9 +292,6 @@ typedef struct
client2cmd_pak client2pak; // 200 bytes
servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; // 773 bytes
resynchend_pak resynchend; //
resynch_pak resynchpak; //
UINT8 resynchgot; //
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
filetx_pak filetxpak; // 139 bytes
fileack_pak fileack;
......@@ -614,7 +433,7 @@ UINT8 GetFreeXCmdSize(void);
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
extern UINT8 hu_resynching;
extern UINT8 hu_redownloadinggamestate;
extern UINT8 adminpassmd5[16];
extern boolean adminpasswordset;
......
......@@ -67,6 +67,7 @@
#include "keys.h"
#include "filesrch.h" // refreshdirmenu, mainwadstally
#include "g_input.h" // tutorial mode control scheming
#include "m_perfstats.h"
#ifdef CMAKECONFIG
#include "config.h"
......@@ -412,7 +413,7 @@ static void D_Display(void)
if (!automapactive && !dedicated && cv_renderview.value)
{
rs_rendercalltime = I_GetTimeMicros();
ps_rendercalltime = I_GetTimeMicros();
if (players[displayplayer].mo || players[displayplayer].playerstate == PST_DEAD)
{
topleft = screens[0] + viewwindowy*vid.width + viewwindowx;
......@@ -459,7 +460,7 @@ static void D_Display(void)
if (postimgtype2)
V_DoPostProcessor(1, postimgtype2, postimgparam2);
}
rs_rendercalltime = I_GetTimeMicros() - rs_rendercalltime;
ps_rendercalltime = I_GetTimeMicros() - ps_rendercalltime;
}
if (lastdraw)
......@@ -473,7 +474,7 @@ static void D_Display(void)
lastdraw = false;
}
rs_uitime = I_GetTimeMicros();
ps_uitime = I_GetTimeMicros();
if (gamestate == GS_LEVEL)
{
......@@ -486,7 +487,7 @@ static void D_Display(void)
}
else
{
rs_uitime = I_GetTimeMicros();
ps_uitime = I_GetTimeMicros();
}
}
......@@ -528,7 +529,7 @@ static void D_Display(void)
CON_Drawer();
rs_uitime = I_GetTimeMicros() - rs_uitime;
ps_uitime = I_GetTimeMicros() - ps_uitime;
//
// wipe update
......@@ -609,90 +610,14 @@ static void D_Display(void)
V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s);
}
if (cv_renderstats.value)
if (cv_perfstats.value)
{
char s[50];
int frametime = I_GetTimeMicros() - rs_prevframetime;
int divisor = 1;
rs_prevframetime = I_GetTimeMicros();
if (rs_rendercalltime > 10000) divisor = 1000;
snprintf(s, sizeof s - 1, "ft %d", frametime / divisor);
V_DrawThinString(30, 10, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "rtot %d", rs_rendercalltime / divisor);
V_DrawThinString(30, 20, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "bsp %d", rs_bsptime / divisor);
V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "nbsp %d", rs_numbspcalls);
V_DrawThinString(80, 10, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "nspr %d", rs_numsprites);
V_DrawThinString(80, 20, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "nnod %d", rs_numdrawnodes);
V_DrawThinString(80, 30, V_MONOSPACE | V_BLUEMAP, s);
snprintf(s, sizeof s - 1, "npob %d", rs_numpolyobjects);
V_DrawThinString(80, 40, V_MONOSPACE | V_BLUEMAP, s);
if (rendermode == render_opengl) // OpenGL specific stats
{
#ifdef HWRENDER
snprintf(s, sizeof s - 1, "nsrt %d", rs_hw_nodesorttime / divisor);
V_DrawThinString(30, 40, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ndrw %d", rs_hw_nodedrawtime / divisor);
V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ssrt %d", rs_hw_spritesorttime / divisor);
V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "sdrw %d", rs_hw_spritedrawtime / divisor);
V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "ui %d", rs_uitime / divisor);
V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "fin %d", rs_swaptime / divisor);
V_DrawThinString(30, 90, V_MONOSPACE | V_YELLOWMAP, s);
snprintf(s, sizeof s - 1, "tic %d", rs_tictime / divisor);
V_DrawThinString(30, 105, V_MONOSPACE | V_GRAYMAP, s);
if (cv_glbatching.value)
{
snprintf(s, sizeof s - 1, "bsrt %d", rs_hw_batchsorttime / divisor);
V_DrawThinString(80, 55, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "bdrw %d", rs_hw_batchdrawtime / divisor);
V_DrawThinString(80, 65, V_MONOSPACE | V_REDMAP, s);
snprintf(s, sizeof s - 1, "npol %d", rs_hw_numpolys);
V_DrawThinString(130, 10, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "ndc %d", rs_hw_numcalls);
V_DrawThinString(130, 20, V_MONOSPACE | V_PURPLEMAP, s);
snprintf(s, sizeof s - 1, "nshd %d", rs_hw_numshaders);
V_DrawThinString(130, 30, V_MONOSPACE | V_PURPLEMAP, s);