Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
4.5 KiB

  1. //========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=====================================================================================//
  6. #include "blackbox.h"
  7. #include "tier0/basetypes.h"
  8. #include "cmd.h"
  9. #include "tier1/utllinkedlist.h"
  10. #include "tier1/convar.h"
  11. #include "tier1/fmtstr.h"
  12. #include "tier1/interface.h"
  13. // memdbgon must be the last include file in a .cpp file!!!
  14. #include "tier0/memdbgon.h"
  15. // development only, off by default for 360
  16. ConVar blackbox( "blackbox", IsX360() ? "0" : "1" );
  17. #define MAX_MESSAGE_SIZE 1024
  18. #define DEFAULT_RECORD_LIMIT 16
  19. static const char* gTypeMap[] =
  20. {
  21. "VCD",
  22. "WAV",
  23. "BOT",
  24. NULL
  25. };
  26. struct CBlackBoxRecord
  27. {
  28. CBlackBoxRecord(const char *new_message)
  29. {
  30. m_time = Plat_FloatTime();
  31. m_message = new char[strlen(new_message)+1];
  32. strcpy(m_message, new_message);
  33. }
  34. ~CBlackBoxRecord() { if (m_message) delete m_message; };
  35. operator const char *() const
  36. {
  37. static CFmtStrN<MAX_MESSAGE_SIZE+16> buf;
  38. double temp = m_time;
  39. int hh = int(temp/(60*60));
  40. int mm = int(temp/60) % 60;
  41. float ss = temp - ((mm + (hh * 60)) * 60);
  42. buf.sprintf( "[%02d:%02d:%02.3f]: %s", hh, mm, ss, m_message );
  43. return buf;
  44. }
  45. double m_time;
  46. char *m_message;
  47. };
  48. class CBlackBox: public IBlackBox
  49. {
  50. public:
  51. CBlackBox();
  52. ~CBlackBox();
  53. virtual void Record(int type, const char *msg);
  54. virtual void SetLimit(int type, unsigned int count);
  55. virtual const char *Get(int type, unsigned int index);
  56. virtual int Count(int type);
  57. virtual void Flush(int type);
  58. virtual const char *GetTypeName(int type);
  59. virtual int GetTypeCount();
  60. enum Types {
  61. VCD,
  62. WAV,
  63. BOT,
  64. TYPE_COUNT
  65. };
  66. private:
  67. bool ValidType(int type) { return (type >= 0 && type < TYPE_COUNT); };
  68. CUtlVector<CBlackBoxRecord *> m_records[TYPE_COUNT];
  69. uint m_record_limits[TYPE_COUNT];
  70. };
  71. CBlackBox gCBlackBox;
  72. IBlackBox *gBlackBox = &gCBlackBox;
  73. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CBlackBox, IBlackBox, BLACKBOX_INTERFACE_VERSION, gCBlackBox );
  74. CBlackBox::CBlackBox()
  75. {
  76. for ( int i = 0; i < TYPE_COUNT; i++ )
  77. {
  78. m_record_limits[i] = DEFAULT_RECORD_LIMIT;
  79. }
  80. }
  81. CBlackBox::~CBlackBox()
  82. {
  83. for (int i = 0; i < TYPE_COUNT; i++)
  84. {
  85. Flush(i);
  86. }
  87. }
  88. void CBlackBox::Record( int type, const char *msg )
  89. {
  90. if ( IsX360() || !blackbox.GetBool() )
  91. return;
  92. if ( !ValidType(type) )
  93. return;
  94. CBlackBoxRecord *new_record = new CBlackBoxRecord( msg );
  95. m_records[type].AddToTail( new_record );
  96. if ( (uint)m_records[type].Count() > m_record_limits[type] )
  97. {
  98. CBlackBoxRecord *old_record = m_records[type].Head();
  99. m_records[type].Remove( 0 );
  100. delete old_record;
  101. }
  102. }
  103. void CBlackBox::SetLimit(int type, unsigned int count)
  104. {
  105. if ( !ValidType( type ))
  106. return;
  107. m_record_limits[type] = count;
  108. }
  109. const char *CBlackBox::Get( int type, unsigned int index )
  110. {
  111. if ( !ValidType( type ))
  112. return NULL;
  113. return (*m_records[type][index]);
  114. }
  115. const char *CBlackBox::GetTypeName( int type )
  116. {
  117. if ( !ValidType( type ))
  118. return NULL;
  119. return gTypeMap[type];
  120. }
  121. int CBlackBox::GetTypeCount()
  122. {
  123. return TYPE_COUNT;
  124. }
  125. int CBlackBox::Count( int type )
  126. {
  127. if ( !ValidType( type ))
  128. return -1;
  129. return m_records[type].Count();
  130. }
  131. void CBlackBox::Flush( int type )
  132. {
  133. if ( !ValidType( type ))
  134. return;
  135. m_records[type].PurgeAndDeleteElements();
  136. }
  137. CON_COMMAND_F( blackbox_record, "Record an entry into the blackbox", FCVAR_DONTRECORD )
  138. {
  139. if ( IsX360() || !blackbox.GetBool() )
  140. return;
  141. if ( args.ArgC() < 2 )
  142. {
  143. Msg( "Insufficient arguments to blackbox_record. Usage: blackbox_record <type> <message>\n" );
  144. return;
  145. }
  146. BlackBox_Record( args[1], args[2] );
  147. }
  148. CON_COMMAND_F( blackbox_dump, "Dump the contents of the blackbox", FCVAR_DONTRECORD )
  149. {
  150. if ( IsX360() )
  151. return;
  152. for ( int type = 0; type < gBlackBox->GetTypeCount(); type++ )
  153. {
  154. for ( int i = 0; i < gBlackBox->Count(type); i++ )
  155. {
  156. Msg( "%s[%d]: %s\n", gBlackBox->GetTypeName( type ), i+1, gBlackBox->Get( type, i ) );
  157. }
  158. }
  159. }
  160. void BlackBox_Record( const char *type, const char *pFormat, ... )
  161. {
  162. if ( IsGameConsole() || !blackbox.GetBool() )
  163. return;
  164. int type_num;
  165. for ( type_num = 0; type_num < gBlackBox->GetTypeCount(); type_num++ )
  166. {
  167. if ( !V_strcasecmp( gBlackBox->GetTypeName( type_num ), type ) )
  168. break;
  169. }
  170. if ( type_num >= gBlackBox->GetTypeCount() )
  171. {
  172. Msg( "Invalid blackbox type: %s\n", type );
  173. return;
  174. }
  175. char szMessage[1024];
  176. va_list marker;
  177. va_start( marker, pFormat);
  178. Q_vsnprintf( szMessage, sizeof( szMessage ), pFormat, marker);
  179. va_end( marker );
  180. //Msg( "Record: %s: %s\n", type, szMessage );
  181. gBlackBox->Record( type_num, szMessage );
  182. }