1 /*
2 ** stats.cpp
3 ** Performance-monitoring statistics
4 **
5 **---------------------------------------------------------------------------
6 ** Copyright 1998-2006 Randy Heit
7 ** All rights reserved.
8 **
9 ** Redistribution and use in source and binary forms, with or without
10 ** modification, are permitted provided that the following conditions
11 ** are met:
12 **
13 ** 1. Redistributions of source code must retain the above copyright
14 **    notice, this list of conditions and the following disclaimer.
15 ** 2. Redistributions in binary form must reproduce the above copyright
16 **    notice, this list of conditions and the following disclaimer in the
17 **    documentation and/or other materials provided with the distribution.
18 ** 3. The name of the author may not be used to endorse or promote products
19 **    derived from this software without specific prior written permission.
20 **
21 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 **---------------------------------------------------------------------------
32 **
33 */
34 
35 #include "doomtype.h"
36 #include "stats.h"
37 #include "v_video.h"
38 #include "v_text.h"
39 #include "hu_stuff.h"
40 #include "st_stuff.h"
41 #include "c_dispatch.h"
42 #include "m_swap.h"
43 #include "sbar.h"
44 
45 
46 #if defined (__APPLE__)
47 
48 mach_timebase_info_data_t cycle_t::s_info;
49 bool cycle_t::s_initialized;
50 
51 #endif // __APPLE__
52 
53 
54 FStat *FStat::FirstStat;
55 
FStat(const char * name)56 FStat::FStat (const char *name)
57 {
58 	m_Name = name;
59 	m_Active = false;
60 	m_Next = FirstStat;
61 	FirstStat = this;
62 }
63 
~FStat()64 FStat::~FStat ()
65 {
66 	FStat **prev = &FirstStat;
67 
68 	while (*prev && *prev != this)
69 		prev = &((*prev)->m_Next)->m_Next;
70 
71 	if (*prev == this)
72 		*prev = m_Next;
73 }
74 
FindStat(const char * name)75 FStat *FStat::FindStat (const char *name)
76 {
77 	FStat *stat = FirstStat;
78 
79 	while (stat && stricmp (name, stat->m_Name))
80 		stat = stat->m_Next;
81 
82 	return stat;
83 }
84 
ToggleStat(const char * name)85 void FStat::ToggleStat (const char *name)
86 {
87 	FStat *stat = FindStat (name);
88 	if (stat)
89 		stat->ToggleStat ();
90 	else
91 		Printf ("Unknown stat: %s\n", name);
92 }
93 
ToggleStat()94 void FStat::ToggleStat ()
95 {
96 	m_Active = !m_Active;
97 	ST_SetNeedRefresh();
98 }
99 
PrintStat()100 void FStat::PrintStat ()
101 {
102 	int fontheight = ConFont->GetHeight() + 1;
103 	int y = SCREENHEIGHT;
104 	int count = 0;
105 
106 	for (FStat *stat = FirstStat; stat != NULL; stat = stat->m_Next)
107 	{
108 		if (stat->m_Active)
109 		{
110 			FString stattext(stat->GetStats());
111 
112 			if (stattext.Len() > 0)
113 			{
114 				y -= fontheight;	// there's at least one line of text
115 				for (unsigned i = 0; i < stattext.Len()-1; i++)
116 				{
117 					// Count number of linefeeds but ignore terminating ones.
118 					if (stattext[i] == '\n') y -= fontheight;
119 				}
120 				screen->DrawText(ConFont, CR_GREEN, 5, y, stattext, TAG_DONE);
121 				count++;
122 			}
123 		}
124 	}
125 	if (count)
126 	{
127 		ST_SetNeedRefresh();
128 	}
129 }
130 
DumpRegisteredStats()131 void FStat::DumpRegisteredStats ()
132 {
133 	FStat *stat = FirstStat;
134 
135 	Printf ("Available stats:\n");
136 	while (stat)
137 	{
138 		Printf (" %c%s\n", stat->m_Active ? '*' : ' ', stat->m_Name);
139 		stat = stat->m_Next;
140 	}
141 }
142 
CCMD(stat)143 CCMD (stat)
144 {
145 	if (argv.argc() != 2)
146 	{
147 		Printf ("Usage: stat <statistics>\n");
148 		FStat::DumpRegisteredStats ();
149 	}
150 	else
151 	{
152 		FStat::ToggleStat (argv[1]);
153 	}
154 }
155