mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Content of commit was originally written by Sal, but as a monolithic commit. The author of this commit is chunking it up for easier review. Simple inversion on the face of things, but with a long tail of consequences, including 19 changed files. Forced uppercase has been applied in a handful of locations where it was aesthetically imperative. Most menus will follow in another commit, so that that may be reverted if we change the default menu font.
704 lines
18 KiB
C
704 lines
18 KiB
C
// SONIC ROBO BLAST 2
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 2020 by Sonic Team Junior.
|
|
//
|
|
// This program is free software distributed under the
|
|
// terms of the GNU General Public License, version 2.
|
|
// See the 'LICENSE' file for more details.
|
|
//-----------------------------------------------------------------------------
|
|
/// \file m_perfstats.c
|
|
/// \brief Performance measurement tools.
|
|
|
|
#include "m_perfstats.h"
|
|
#include "v_video.h"
|
|
#include "i_video.h"
|
|
#include "d_netcmd.h"
|
|
#include "r_main.h"
|
|
#include "i_system.h"
|
|
#include "i_time.h"
|
|
#include "z_zone.h"
|
|
#include "p_local.h"
|
|
#include "g_game.h"
|
|
|
|
#ifdef HWRENDER
|
|
#include "hardware/hw_main.h"
|
|
#endif
|
|
|
|
struct perfstatcol;
|
|
struct perfstatrow;
|
|
|
|
typedef struct perfstatcol perfstatcol_t;
|
|
typedef struct perfstatrow perfstatrow_t;
|
|
|
|
struct perfstatcol {
|
|
INT32 lores_x;
|
|
INT32 hires_x;
|
|
INT32 color;
|
|
perfstatrow_t * rows;
|
|
};
|
|
|
|
struct perfstatrow {
|
|
const char * lores_label;
|
|
const char * hires_label;
|
|
void * value;
|
|
};
|
|
|
|
static precise_t ps_frametime = 0;
|
|
|
|
precise_t ps_tictime = 0;
|
|
|
|
precise_t ps_playerthink_time = 0;
|
|
precise_t ps_botticcmd_time = 0;
|
|
precise_t ps_thinkertime = 0;
|
|
|
|
precise_t ps_thlist_times[NUM_ACTIVETHINKERLISTS];
|
|
precise_t ps_acs_time = 0;
|
|
|
|
int ps_checkposition_calls = 0;
|
|
|
|
precise_t ps_lua_thinkframe_time = 0;
|
|
int ps_lua_mobjhooks = 0;
|
|
|
|
// dynamically allocated resizeable array for thinkframe hook stats
|
|
ps_hookinfo_t *thinkframe_hooks = NULL;
|
|
int thinkframe_hooks_length = 0;
|
|
int thinkframe_hooks_capacity = 16;
|
|
|
|
ps_botinfo_t ps_bots[MAXPLAYERS];
|
|
|
|
static INT32 draw_row;
|
|
|
|
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
|
|
{
|
|
if (!thinkframe_hooks)
|
|
{
|
|
// array needs to be initialized
|
|
thinkframe_hooks = Z_Malloc(sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL);
|
|
}
|
|
if (index >= thinkframe_hooks_capacity)
|
|
{
|
|
// array needs more space, realloc with double size
|
|
thinkframe_hooks_capacity *= 2;
|
|
thinkframe_hooks = Z_Realloc(thinkframe_hooks,
|
|
sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL);
|
|
}
|
|
thinkframe_hooks[index].time_taken = time_taken;
|
|
memcpy(thinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char));
|
|
// since the values are set sequentially from begin to end, the last call should leave
|
|
// the correct value to this variable
|
|
thinkframe_hooks_length = index + 1;
|
|
}
|
|
|
|
void PS_ResetBotInfo(void)
|
|
{
|
|
memset(ps_bots, 0, sizeof(ps_bots));
|
|
ps_botticcmd_time = 0;
|
|
}
|
|
|
|
static void PS_SetFrameTime(void)
|
|
{
|
|
precise_t currenttime = I_GetPreciseTime();
|
|
ps_frametime = currenttime - ps_prevframetime;
|
|
ps_prevframetime = currenttime;
|
|
}
|
|
|
|
static boolean M_HighResolution(void)
|
|
{
|
|
return (vid.width >= 640 && vid.height >= 400);
|
|
}
|
|
|
|
enum {
|
|
PERF_TIME,
|
|
PERF_COUNT,
|
|
};
|
|
|
|
static void M_DrawPerfString(perfstatcol_t *col, int type)
|
|
{
|
|
const boolean hires = M_HighResolution();
|
|
|
|
INT32 draw_flags = V_MONOSPACE | col->color;
|
|
|
|
perfstatrow_t * row;
|
|
|
|
int value;
|
|
|
|
if (hires)
|
|
draw_flags |= 0;
|
|
|
|
for (row = col->rows; row->lores_label; ++row)
|
|
{
|
|
if (type == PERF_TIME)
|
|
value = (*(precise_t *)row->value) / (I_GetPrecisePrecision() / 1000000);
|
|
else
|
|
value = *(int *)row->value;
|
|
|
|
if (hires)
|
|
{
|
|
V_DrawSmallString(col->hires_x, draw_row, draw_flags,
|
|
va("%s %d", row->hires_label, value));
|
|
|
|
draw_row += 5;
|
|
}
|
|
else
|
|
{
|
|
V_DrawThinString(col->lores_x, draw_row, draw_flags,
|
|
va("%s %d", row->lores_label, value));
|
|
|
|
draw_row += 8;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void M_DrawPerfTiming(perfstatcol_t *col)
|
|
{
|
|
M_DrawPerfString(col, PERF_TIME);
|
|
}
|
|
|
|
static void M_DrawPerfCount(perfstatcol_t *col)
|
|
{
|
|
M_DrawPerfString(col, PERF_COUNT);
|
|
}
|
|
|
|
static void M_DrawRenderStats(void)
|
|
{
|
|
const boolean hires = M_HighResolution();
|
|
|
|
const int half_row = hires ? 5 : 4;
|
|
|
|
precise_t extrarendertime;
|
|
|
|
perfstatrow_t frametime_row[] = {
|
|
{"frmtime", "Frame time: ", &ps_frametime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t rendercalltime_row[] = {
|
|
{"drwtime", "3d rendering: ", &ps_rendercalltime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t opengltime_row[] = {
|
|
{"skybox ", "Skybox render: ", &ps_hw_skyboxtime},
|
|
{"bsptime", "RenderBSPNode: ", &ps_bsptime},
|
|
{"nodesrt", "Drwnode sort: ", &ps_hw_nodesorttime},
|
|
{"nodedrw", "Drwnode render:", &ps_hw_nodedrawtime},
|
|
{"sprsort", "Sprite sort: ", &ps_hw_spritesorttime},
|
|
{"sprdraw", "Sprite render: ", &ps_hw_spritedrawtime},
|
|
{"other ", "Other: ", &extrarendertime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t softwaretime_row[] = {
|
|
{"bsptime", "RenderBSPNode: ", &ps_bsptime},
|
|
{"sprclip", "R_ClipSprites: ", &ps_sw_spritecliptime},
|
|
{"portals", "Portals+Skybox:", &ps_sw_portaltime},
|
|
{"planes ", "R_DrawPlanes: ", &ps_sw_planetime},
|
|
{"masked ", "R_DrawMasked: ", &ps_sw_maskedtime},
|
|
{"other ", "Other: ", &extrarendertime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t uiswaptime_row[] = {
|
|
{"ui ", "UI render: ", &ps_uitime},
|
|
{"finupdt", "I_FinishUpdate:", &ps_swaptime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t tictime_row[] = {
|
|
{"logic ", "Game logic: ", &ps_tictime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t rendercalls_row[] = {
|
|
{"bspcall", "BSP calls: ", &ps_numbspcalls},
|
|
{"sprites", "Sprites: ", &ps_numsprites},
|
|
{"drwnode", "Drawnodes: ", &ps_numdrawnodes},
|
|
{"plyobjs", "Polyobjects: ", &ps_numpolyobjects},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t batchtime_row[] = {
|
|
{"batsort", "Batch sort: ", &ps_hw_batchsorttime},
|
|
{"batdraw", "Batch render:", &ps_hw_batchdrawtime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t batchcount_row[] = {
|
|
{"polygon", "Polygons: ", &ps_hw_numpolys},
|
|
{"vertex ", "Vertices: ", &ps_hw_numverts},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t batchcalls_row[] = {
|
|
{"drwcall", "Draw calls:", &ps_hw_numcalls},
|
|
{"shaders", "Shaders: ", &ps_hw_numshaders},
|
|
{"texture", "Textures: ", &ps_hw_numtextures},
|
|
{"polyflg", "Polyflags: ", &ps_hw_numpolyflags},
|
|
{"colors ", "Colors: ", &ps_hw_numcolors},
|
|
{0}
|
|
};
|
|
|
|
perfstatcol_t frametime_col = {20, 20, V_YELLOWMAP, frametime_row};
|
|
perfstatcol_t rendercalltime_col = {20, 20, V_YELLOWMAP, rendercalltime_row};
|
|
|
|
perfstatcol_t opengltime_col = {24, 24, V_YELLOWMAP, opengltime_row};
|
|
perfstatcol_t softwaretime_col = {24, 24, V_YELLOWMAP, softwaretime_row};
|
|
|
|
perfstatcol_t uiswaptime_col = {20, 20, V_YELLOWMAP, uiswaptime_row};
|
|
perfstatcol_t tictime_col = {20, 20, V_GRAYMAP, tictime_row};
|
|
|
|
perfstatcol_t rendercalls_col = {90, 115, V_BLUEMAP, rendercalls_row};
|
|
|
|
perfstatcol_t batchtime_col = {90, 115, V_REDMAP, batchtime_row};
|
|
|
|
perfstatcol_t batchcount_col = {155, 200, V_PURPLEMAP, batchcount_row};
|
|
perfstatcol_t batchcalls_col = {220, 200, V_PURPLEMAP, batchcalls_row};
|
|
|
|
|
|
boolean rendering = G_GamestateUsesLevel();
|
|
|
|
draw_row = 10;
|
|
M_DrawPerfTiming(&frametime_col);
|
|
|
|
if (rendering)
|
|
{
|
|
M_DrawPerfTiming(&rendercalltime_col);
|
|
|
|
// Remember to update this calculation when adding more 3d rendering stats!
|
|
extrarendertime = ps_rendercalltime - ps_bsptime;
|
|
|
|
#ifdef HWRENDER
|
|
if (rendermode == render_opengl)
|
|
{
|
|
extrarendertime -=
|
|
ps_hw_skyboxtime +
|
|
ps_hw_nodesorttime +
|
|
ps_hw_nodedrawtime +
|
|
ps_hw_spritesorttime +
|
|
ps_hw_spritedrawtime;
|
|
|
|
if (cv_glbatching.value)
|
|
{
|
|
extrarendertime -=
|
|
ps_hw_batchsorttime +
|
|
ps_hw_batchdrawtime;
|
|
}
|
|
|
|
M_DrawPerfTiming(&opengltime_col);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
extrarendertime -=
|
|
ps_sw_spritecliptime +
|
|
ps_sw_portaltime +
|
|
ps_sw_planetime +
|
|
ps_sw_maskedtime;
|
|
|
|
M_DrawPerfTiming(&softwaretime_col);
|
|
}
|
|
}
|
|
|
|
M_DrawPerfTiming(&uiswaptime_col);
|
|
|
|
draw_row += half_row;
|
|
M_DrawPerfTiming(&tictime_col);
|
|
|
|
if (rendering)
|
|
{
|
|
draw_row = 10;
|
|
M_DrawPerfCount(&rendercalls_col);
|
|
|
|
#ifdef HWRENDER
|
|
if (rendermode == render_opengl && cv_glbatching.value)
|
|
{
|
|
draw_row += half_row;
|
|
M_DrawPerfTiming(&batchtime_col);
|
|
|
|
draw_row = 10;
|
|
M_DrawPerfCount(&batchcount_col);
|
|
|
|
if (hires)
|
|
draw_row += half_row;
|
|
else
|
|
draw_row = 10;
|
|
|
|
M_DrawPerfCount(&batchcalls_col);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static void M_DrawTickStats(void)
|
|
{
|
|
int i = 0;
|
|
thinker_t *thinker;
|
|
int thinkercount = 0;
|
|
int polythcount = 0;
|
|
int mainthcount = 0;
|
|
int mobjcount = 0;
|
|
int nothinkcount = 0;
|
|
int scenerycount = 0;
|
|
int regularcount = 0;
|
|
int dynslopethcount = 0;
|
|
int precipcount = 0;
|
|
int removecount = 0;
|
|
|
|
precise_t extratime =
|
|
ps_tictime -
|
|
ps_playerthink_time -
|
|
ps_thinkertime -
|
|
ps_lua_thinkframe_time -
|
|
ps_acs_time;
|
|
|
|
perfstatrow_t tictime_row[] = {
|
|
{"logic ", "Game logic: ", &ps_tictime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t thinker_time_row[] = {
|
|
{"plrthnk", "P_PlayerThink: ", &ps_playerthink_time},
|
|
{"thnkers", "P_RunThinkers: ", &ps_thinkertime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t detailed_thinker_time_row[] = {
|
|
{"plyobjs", "Polyobjects: ", &ps_thlist_times[THINK_POLYOBJ]},
|
|
{"main ", "Main: ", &ps_thlist_times[THINK_MAIN]},
|
|
{"mobjs ", "Mobjs: ", &ps_thlist_times[THINK_MOBJ]},
|
|
{"dynslop", "Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE]},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t extra_thinker_time_row[] = {
|
|
{"lthinkf", "LUAh_ThinkFrame:", &ps_lua_thinkframe_time},
|
|
{"acs ", "ACS_Tick: ", &ps_acs_time},
|
|
{"botcmd ", "Bot logic: ", &ps_botticcmd_time},
|
|
{"other ", "Other: ", &extratime},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t thinkercount_row[] = {
|
|
{"thnkers", "Thinkers: ", &thinkercount},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t detailed_thinkercount_row[] = {
|
|
{"plyobjs", "Polyobjects: ", &polythcount},
|
|
{"main ", "Main: ", &mainthcount},
|
|
{"mobjs ", "Mobjs: ", &mobjcount},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t mobjthinkercount_row[] = {
|
|
{"regular", "Regular: ", ®ularcount},
|
|
{"scenery", "Scenery: ", &scenerycount},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t nothinkcount_row[] = {
|
|
{"nothink", "Nothink: ", ¬hinkcount},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t detailed_thinkercount_row2[] = {
|
|
{"dynslop", "Dynamic slopes: ", &dynslopethcount},
|
|
{"precip ", "Precipitation: ", &precipcount},
|
|
{"remove ", "Pending removal:", &removecount},
|
|
{0}
|
|
};
|
|
|
|
perfstatrow_t misc_calls_row[] = {
|
|
{"lmhook", "Lua mobj hooks: ", &ps_lua_mobjhooks},
|
|
{"chkpos", "P_CheckPosition:", &ps_checkposition_calls},
|
|
{0}
|
|
};
|
|
|
|
perfstatcol_t tictime_col = {20, 20, V_YELLOWMAP, tictime_row};
|
|
perfstatcol_t thinker_time_col = {24, 24, V_YELLOWMAP, thinker_time_row};
|
|
perfstatcol_t detailed_thinker_time_col = {28, 28, V_YELLOWMAP, detailed_thinker_time_row};
|
|
perfstatcol_t extra_thinker_time_col = {24, 24, V_YELLOWMAP, extra_thinker_time_row};
|
|
|
|
perfstatcol_t thinkercount_col = {90, 115, V_BLUEMAP, thinkercount_row};
|
|
perfstatcol_t detailed_thinkercount_col = {94, 119, V_BLUEMAP, detailed_thinkercount_row};
|
|
perfstatcol_t mobjthinkercount_col = {98, 123, V_BLUEMAP, mobjthinkercount_row};
|
|
perfstatcol_t nothinkcount_col = {98, 123, V_BLUEMAP, nothinkcount_row};
|
|
perfstatcol_t detailed_thinkercount_col2 = {94, 119, V_BLUEMAP, detailed_thinkercount_row2};
|
|
perfstatcol_t misc_calls_col = {170, 216, V_PURPLEMAP, misc_calls_row};
|
|
|
|
for (i = 0; i < NUM_THINKERLISTS; i++)
|
|
{
|
|
for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next)
|
|
{
|
|
thinkercount++;
|
|
if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
|
removecount++;
|
|
else if (i == THINK_POLYOBJ)
|
|
polythcount++;
|
|
else if (i == THINK_MAIN)
|
|
mainthcount++;
|
|
else if (i == THINK_MOBJ)
|
|
{
|
|
if (thinker->function.acp1 == (actionf_p1)P_MobjThinker)
|
|
{
|
|
mobj_t *mobj = (mobj_t*)thinker;
|
|
mobjcount++;
|
|
if (mobj->flags & MF_NOTHINK)
|
|
nothinkcount++;
|
|
else if (mobj->flags & MF_SCENERY)
|
|
scenerycount++;
|
|
else
|
|
regularcount++;
|
|
}
|
|
}
|
|
else if (i == THINK_DYNSLOPE)
|
|
dynslopethcount++;
|
|
else if (i == THINK_PRECIP)
|
|
precipcount++;
|
|
}
|
|
}
|
|
|
|
draw_row = 10;
|
|
M_DrawPerfTiming(&tictime_col);
|
|
M_DrawPerfTiming(&thinker_time_col);
|
|
M_DrawPerfTiming(&detailed_thinker_time_col);
|
|
M_DrawPerfTiming(&extra_thinker_time_col);
|
|
|
|
draw_row = 10;
|
|
M_DrawPerfCount(&thinkercount_col);
|
|
M_DrawPerfCount(&detailed_thinkercount_col);
|
|
M_DrawPerfCount(&mobjthinkercount_col);
|
|
|
|
if (nothinkcount)
|
|
M_DrawPerfCount(¬hinkcount_col);
|
|
|
|
M_DrawPerfCount(&detailed_thinkercount_col2);
|
|
|
|
if (M_HighResolution())
|
|
{
|
|
V_DrawSmallString(212, 10, V_MONOSPACE | V_PURPLEMAP, "Calls:");
|
|
|
|
draw_row = 15;
|
|
}
|
|
else
|
|
{
|
|
draw_row = 10;
|
|
}
|
|
|
|
M_DrawPerfCount(&misc_calls_col);
|
|
}
|
|
|
|
void M_DrawPerfStats(void)
|
|
{
|
|
char s[363];
|
|
|
|
PS_SetFrameTime();
|
|
|
|
if (cv_perfstats.value == PS_RENDER) // rendering
|
|
{
|
|
M_DrawRenderStats();
|
|
}
|
|
else if (cv_perfstats.value == PS_LOGIC) // logic
|
|
{
|
|
M_DrawTickStats();
|
|
}
|
|
else if (cv_perfstats.value == PS_BOT) // bot ticcmd
|
|
{
|
|
if (vid.width < 640 || vid.height < 400) // low resolution
|
|
{
|
|
// it's not gonna fit very well..
|
|
V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, "Not available for resolutions below 640x400");
|
|
}
|
|
else // high resolution
|
|
{
|
|
precise_t otherTime = 0;
|
|
int i;
|
|
|
|
// text writing position
|
|
int x = 2;
|
|
int y = 4;
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
{
|
|
if (ps_bots[i].isBot == false)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
snprintf(s, sizeof s - 1, "Bot %d (%s):", i + 1, player_names[i]);
|
|
V_DrawSmallString(x, y, V_MONOSPACE | V_GRAYMAP, s);
|
|
|
|
snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].total) / (I_GetPrecisePrecision() / 1000000)));
|
|
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_GRAYMAP, s);
|
|
|
|
y += 4; // repeated code!
|
|
if (y > 192)
|
|
{
|
|
y = 4;
|
|
x += 106;
|
|
if (x > 214)
|
|
break;
|
|
}
|
|
|
|
snprintf(s, sizeof s - 1, "Prediction:");
|
|
V_DrawSmallString(x, y, V_MONOSPACE | V_YELLOWMAP, s);
|
|
|
|
snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].prediction) / (I_GetPrecisePrecision() / 1000000)));
|
|
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE, s);
|
|
|
|
y += 4; // repeated code!
|
|
if (y > 192)
|
|
{
|
|
y = 4;
|
|
x += 106;
|
|
if (x > 214)
|
|
break;
|
|
}
|
|
|
|
snprintf(s, sizeof s - 1, "Nudge:");
|
|
V_DrawSmallString(x, y, V_MONOSPACE | V_YELLOWMAP, s);
|
|
|
|
snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].nudge) / (I_GetPrecisePrecision() / 1000000)));
|
|
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE, s);
|
|
|
|
y += 4; // repeated code!
|
|
if (y > 192)
|
|
{
|
|
y = 4;
|
|
x += 106;
|
|
if (x > 214)
|
|
break;
|
|
}
|
|
|
|
snprintf(s, sizeof s - 1, "Item:");
|
|
V_DrawSmallString(x, y, V_MONOSPACE | V_YELLOWMAP, s);
|
|
|
|
snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].item) / (I_GetPrecisePrecision() / 1000000)));
|
|
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE, s);
|
|
|
|
y += 4; // repeated code!
|
|
if (y > 192)
|
|
{
|
|
y = 4;
|
|
x += 106;
|
|
if (x > 214)
|
|
break;
|
|
}
|
|
|
|
snprintf(s, sizeof s - 1, "Other:");
|
|
V_DrawSmallString(x, y, V_MONOSPACE | V_YELLOWMAP, s);
|
|
|
|
otherTime = ps_bots[i].total - ps_bots[i].prediction - ps_bots[i].nudge - ps_bots[i].item;
|
|
snprintf(s, sizeof s - 1, "%ld", (long)(otherTime / (I_GetPrecisePrecision() / 1000000)));
|
|
V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE, s);
|
|
|
|
y += 4; // repeated code!
|
|
if (y > 192)
|
|
{
|
|
y = 4;
|
|
x += 106;
|
|
if (x > 214)
|
|
break;
|
|
}
|
|
|
|
// add an extra space
|
|
y += 4; // repeated code!
|
|
if (y > 192)
|
|
{
|
|
y = 4;
|
|
x += 106;
|
|
if (x > 214)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (cv_perfstats.value == PS_THINKFRAME) // lua thinkframe
|
|
{
|
|
if (G_GamestateUsesLevel() == false)
|
|
return;
|
|
|
|
if (vid.width < 640 || vid.height < 400) // low resolution
|
|
{
|
|
// it's not gonna fit very well..
|
|
V_DrawThinString(30, 30, V_MONOSPACE | V_YELLOWMAP, "Not available for resolutions below 640x400");
|
|
}
|
|
else // high resolution
|
|
{
|
|
int i;
|
|
// text writing position
|
|
int x = 2;
|
|
int y = 4;
|
|
UINT32 text_color;
|
|
char tempbuffer[LUA_IDSIZE];
|
|
char last_mod_name[LUA_IDSIZE];
|
|
last_mod_name[0] = '\0';
|
|
for (i = 0; i < thinkframe_hooks_length; i++)
|
|
{
|
|
char* str = thinkframe_hooks[i].short_src;
|
|
char* tempstr = tempbuffer;
|
|
int len = (int)strlen(str);
|
|
char* str_ptr;
|
|
if (strcmp(".lua", str + len - 4) == 0)
|
|
{
|
|
str[len-4] = '\0'; // remove .lua at end
|
|
len -= 4;
|
|
}
|
|
// we locate the wad/pk3 name in the string and compare it to
|
|
// what we found on the previous iteration.
|
|
// if the name has changed, print it out on the screen
|
|
strcpy(tempstr, str);
|
|
str_ptr = strrchr(tempstr, '|');
|
|
if (str_ptr)
|
|
{
|
|
*str_ptr = '\0';
|
|
str = str_ptr + 1; // this is the name of the hook without the mod file name
|
|
str_ptr = strrchr(tempstr, PATHSEP[0]);
|
|
if (str_ptr)
|
|
tempstr = str_ptr + 1;
|
|
// tempstr should now point to the mod name, (wad/pk3) possibly truncated
|
|
if (strcmp(tempstr, last_mod_name) != 0)
|
|
{
|
|
strcpy(last_mod_name, tempstr);
|
|
len = (int)strlen(tempstr);
|
|
if (len > 25)
|
|
tempstr += len - 25;
|
|
snprintf(s, sizeof s - 1, "%s", tempstr);
|
|
V_DrawSmallString(x, y, V_MONOSPACE | V_GRAYMAP, s);
|
|
y += 4; // repeated code!
|
|
if (y > 192)
|
|
{
|
|
y = 4;
|
|
x += 106;
|
|
if (x > 214)
|
|
break;
|
|
}
|
|
}
|
|
text_color = V_YELLOWMAP;
|
|
}
|
|
else
|
|
{
|
|
// probably a standalone lua file
|
|
// cut off the folder if it's there
|
|
str_ptr = strrchr(tempstr, PATHSEP[0]);
|
|
if (str_ptr)
|
|
str = str_ptr + 1;
|
|
text_color = 0; // white
|
|
}
|
|
len = (int)strlen(str);
|
|
if (len > 20)
|
|
str += len - 20;
|
|
snprintf(s, sizeof s - 1, "%20s: %ld", str, (long)((thinkframe_hooks[i].time_taken) / (I_GetPrecisePrecision() / 1000000)));
|
|
V_DrawSmallString(x, y, V_MONOSPACE | text_color, s);
|
|
y += 4; // repeated code!
|
|
if (y > 192)
|
|
{
|
|
y = 4;
|
|
x += 106;
|
|
if (x > 214)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|