Team Fortress 2 Source Code as on 22/4/2020
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.

1440 lines
38 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // SHOW_MEMDUMP.CPP
  4. //
  5. // Show Mem Dump Display.
  6. //=====================================================================================//
  7. #include "vxconsole.h"
  8. #define ID_SHOWMEMDUMP_LISTVIEW 100
  9. // column id, pool mode
  10. #define ID_DUMPPOOL_POOL 0
  11. #define ID_DUMPPOOL_SIZE 1
  12. #define ID_DUMPPOOL_ALLOCATED 2
  13. #define ID_DUMPPOOL_FREE 3
  14. #define ID_DUMPPOOL_COMMITTED 4
  15. #define ID_DUMPPOOL_COMMITTEDSIZE 5
  16. // column id, detailed mode
  17. #define ID_DUMPDETAIL_ALLOCATION 0
  18. #define ID_DUMPDETAIL_CURRENTSIZE 1
  19. #define ID_DUMPDETAIL_PEAKSIZE 2
  20. #define ID_DUMPDETAIL_TOTALSIZE 3
  21. #define ID_DUMPDETAIL_OVERHEAD 4
  22. #define ID_DUMPDETAIL_PEAKOVERHEAD 5
  23. #define ID_DUMPDETAIL_TIME 6
  24. #define ID_DUMPDETAIL_CURRENTCOUNT 7
  25. #define ID_DUMPDETAIL_PEAKCOUNT 8
  26. #define ID_DUMPDETAIL_TOTALCOUNT 9
  27. #define ID_DUMPDETAIL_LTE16 10
  28. #define ID_DUMPDETAIL_LTE32 11
  29. #define ID_DUMPDETAIL_LTE128 12
  30. #define ID_DUMPDETAIL_LTE1024 13
  31. #define ID_DUMPDETAIL_GT1024 14
  32. #define SHOW_BYTES 0
  33. #define SHOW_KILOBYTES 1
  34. #define SHOW_MEGABYTES 2
  35. #define FORMAT_POOLS 0
  36. #define FORMAT_DETAILS 1
  37. struct MemoryPool_t
  38. {
  39. int pool;
  40. char poolBuff[32];
  41. int size;
  42. char sizeBuff[32];
  43. int allocated;
  44. char allocatedBuff[32];
  45. int free;
  46. char freeBuff[32];
  47. int committed;
  48. char committedBuff[32];
  49. int committedSize;
  50. char committedSizeBuff[32];
  51. };
  52. struct MemoryDetail_t
  53. {
  54. char *pAllocationName;
  55. int currentSize;
  56. char currentSizeBuff[32];
  57. int peakSize;
  58. char peakSizeBuff[32];
  59. int totalSize;
  60. char totalSizeBuff[32];
  61. int overheadSize;
  62. char overheadSizeBuff[32];
  63. int peakOverheadSize;
  64. char peakOverheadSizeBuff[32];
  65. int time;
  66. char timeBuff[32];
  67. int currentCount;
  68. char currentCountBuff[32];
  69. int peakCount;
  70. char peakCountBuff[32];
  71. int totalCount;
  72. char totalCountBuff[32];
  73. int lte16;
  74. char lte16Buff[32];
  75. int lte32;
  76. char lte32Buff[32];
  77. int lte128;
  78. char lte128Buff[32];
  79. int lte1024;
  80. char lte1024Buff[32];
  81. int gt1024;
  82. char gt1024Buff[32];
  83. };
  84. struct memory_t
  85. {
  86. int listIndex;
  87. MemoryPool_t pool;
  88. MemoryDetail_t detail;
  89. };
  90. struct label_t
  91. {
  92. const CHAR* name;
  93. int width;
  94. int subItemIndex;
  95. CHAR nameBuff[64];
  96. };
  97. HWND g_showMemDump_hWnd;
  98. HWND g_showMemDump_hWndListView;
  99. RECT g_showMemDump_windowRect;
  100. int g_showMemDump_sortColumn;
  101. int g_showMemDump_sortDescending;
  102. memory_t *g_showMemDump_pMemory;
  103. int g_showMemDump_numMemory;
  104. int g_showMemDump_showBytes;
  105. bool g_showMemDump_bCollapseOutput;
  106. char g_showMemDump_currentFilename[MAX_PATH];
  107. int g_showMemDump_format;
  108. void ShowMemDump_Parse( const char *pBuffer, int fileSize );
  109. label_t g_showMemDump_PoolLabels[] =
  110. {
  111. {"Pool", 120, ID_DUMPPOOL_POOL},
  112. {"Size", 120, ID_DUMPPOOL_SIZE},
  113. {"Allocated Count", 120, ID_DUMPPOOL_ALLOCATED},
  114. {"Free Count", 120, ID_DUMPPOOL_FREE},
  115. {"Committed Count", 120, ID_DUMPPOOL_COMMITTED},
  116. {"Committed Size", 120, ID_DUMPPOOL_COMMITTEDSIZE},
  117. };
  118. label_t g_showMemDump_DetailLabels[] =
  119. {
  120. {"Allocation", 200, ID_DUMPDETAIL_ALLOCATION},
  121. {"Current Size", 120, ID_DUMPDETAIL_CURRENTSIZE},
  122. {"Peak Size", 120, ID_DUMPDETAIL_PEAKSIZE},
  123. {"Total Allocations", 120, ID_DUMPDETAIL_TOTALSIZE},
  124. {"Overhead Size", 120, ID_DUMPDETAIL_OVERHEAD},
  125. {"Peak Overhead Size", 120, ID_DUMPDETAIL_PEAKOVERHEAD},
  126. {"Time (ms)", 120, ID_DUMPDETAIL_TIME},
  127. {"Current Count", 120, ID_DUMPDETAIL_CURRENTCOUNT},
  128. {"Peak Count", 120, ID_DUMPDETAIL_PEAKCOUNT},
  129. {"Total Count", 120, ID_DUMPDETAIL_TOTALCOUNT},
  130. {"<=16 bytes", 100, ID_DUMPDETAIL_LTE16},
  131. {"17-32 bytes", 100, ID_DUMPDETAIL_LTE32},
  132. {"33-128 bytes", 100, ID_DUMPDETAIL_LTE128},
  133. {"129-1024 bytes", 100, ID_DUMPDETAIL_LTE1024},
  134. {"> 1024 bytes", 100, ID_DUMPDETAIL_GT1024},
  135. };
  136. //-----------------------------------------------------------------------------
  137. // ShowMemDump_FormatSize
  138. //
  139. //-----------------------------------------------------------------------------
  140. char *ShowMemDump_FormatSize( int size, char *pBuff, bool bUnits )
  141. {
  142. switch ( g_showMemDump_showBytes )
  143. {
  144. case SHOW_BYTES:
  145. sprintf( pBuff, "%d", size );
  146. break;
  147. case SHOW_KILOBYTES:
  148. sprintf( pBuff, "%.2f", (float)size/1024.0f );
  149. if ( bUnits )
  150. strcat( pBuff, " K");
  151. break;
  152. case SHOW_MEGABYTES:
  153. sprintf( pBuff, "%.2f", (float)size/(1024.0f*1024.0f) );
  154. if ( bUnits )
  155. strcat( pBuff, " MB");
  156. break;
  157. }
  158. return pBuff;
  159. }
  160. //-----------------------------------------------------------------------------
  161. // ShowMemDump_SaveConfig
  162. //
  163. //-----------------------------------------------------------------------------
  164. void ShowMemDump_SaveConfig()
  165. {
  166. char buff[256];
  167. Sys_SetRegistryInteger( "showMemDumpSortColumn", g_showMemDump_sortColumn );
  168. Sys_SetRegistryInteger( "showMemDumpSortDescending", g_showMemDump_sortDescending );
  169. Sys_SetRegistryInteger( "showMemDumpShowBytes", g_showMemDump_showBytes );
  170. WINDOWPLACEMENT wp;
  171. memset( &wp, 0, sizeof( wp ) );
  172. wp.length = sizeof( WINDOWPLACEMENT );
  173. GetWindowPlacement( g_showMemDump_hWnd, &wp );
  174. g_showMemDump_windowRect = wp.rcNormalPosition;
  175. sprintf( buff, "%d %d %d %d", g_showMemDump_windowRect.left, g_showMemDump_windowRect.top, g_showMemDump_windowRect.right, g_showMemDump_windowRect.bottom );
  176. Sys_SetRegistryString( "showMemDumpWindowRect", buff );
  177. }
  178. //-----------------------------------------------------------------------------
  179. // ShowMemDump_LoadConfig
  180. //
  181. //-----------------------------------------------------------------------------
  182. void ShowMemDump_LoadConfig()
  183. {
  184. int numArgs;
  185. char buff[256];
  186. Sys_GetRegistryInteger( "showMemDumpSortColumn", 0, g_showMemDump_sortColumn );
  187. Sys_GetRegistryInteger( "showMemDumpSortDescending", false, g_showMemDump_sortDescending );
  188. Sys_GetRegistryInteger( "showMemDumpShowBytes", SHOW_KILOBYTES, g_showMemDump_showBytes );
  189. Sys_GetRegistryString( "showMemDumpWindowRect", buff, "", sizeof( buff ) );
  190. numArgs = sscanf( buff, "%d %d %d %d", &g_showMemDump_windowRect.left, &g_showMemDump_windowRect.top, &g_showMemDump_windowRect.right, &g_showMemDump_windowRect.bottom );
  191. if ( numArgs != 4 || g_showMemDump_windowRect.left < 0 || g_showMemDump_windowRect.top < 0 || g_showMemDump_windowRect.right < 0 || g_showMemDump_windowRect.bottom < 0 )
  192. memset( &g_showMemDump_windowRect, 0, sizeof( g_showMemDump_windowRect ) );
  193. }
  194. //-----------------------------------------------------------------------------
  195. // ShowMemDump_Clear
  196. //
  197. //-----------------------------------------------------------------------------
  198. void ShowMemDump_Clear()
  199. {
  200. // delete all the list view entries
  201. if ( g_showMemDump_hWnd )
  202. {
  203. ListView_DeleteAllItems( g_showMemDump_hWndListView );
  204. }
  205. if ( !g_showMemDump_pMemory )
  206. return;
  207. for ( int i=0; i<g_showMemDump_numMemory; i++ )
  208. {
  209. delete [] g_showMemDump_pMemory[i].detail.pAllocationName;
  210. }
  211. Sys_Free( g_showMemDump_pMemory );
  212. g_showMemDump_pMemory = NULL;
  213. g_showMemDump_numMemory = 0;
  214. }
  215. //-----------------------------------------------------------------------------
  216. // ShowMemDump_Export
  217. //
  218. //-----------------------------------------------------------------------------
  219. void ShowMemDump_Export()
  220. {
  221. OPENFILENAME ofn;
  222. char logFilename[MAX_PATH];
  223. int retval;
  224. FILE* fp;
  225. int i;
  226. char buff[64];
  227. if ( g_showMemDump_format != FORMAT_DETAILS )
  228. {
  229. return;
  230. }
  231. memset( &ofn, 0, sizeof( ofn ) );
  232. ofn.lStructSize = sizeof( ofn );
  233. ofn.hwndOwner = g_showMemDump_hWnd;
  234. ofn.lpstrFile = logFilename;
  235. ofn.lpstrFile[0] = '\0';
  236. ofn.nMaxFile = sizeof( logFilename );
  237. ofn.lpstrFilter = "Excel CSV\0*.CSV\0All Files\0*.*\0";
  238. ofn.nFilterIndex = 1;
  239. ofn.lpstrFileTitle = NULL;
  240. ofn.nMaxFileTitle = 0;
  241. ofn.lpstrInitialDir = "c:\\";
  242. ofn.Flags = OFN_PATHMUSTEXIST;
  243. // display the Open dialog box.
  244. retval = GetOpenFileName( &ofn );
  245. if ( !retval )
  246. return;
  247. Sys_AddExtension( ".csv", logFilename, sizeof( logFilename ) );
  248. fp = fopen( logFilename, "wt+" );
  249. if ( !fp )
  250. return;
  251. // labels
  252. fprintf( fp, "Allocation Type" );
  253. fprintf( fp, ",Current Size" );
  254. fprintf( fp, ",Peak Size" );
  255. fprintf( fp, ",Total Allocations" );
  256. fprintf( fp, ",Overhead Size" );
  257. fprintf( fp, ",Peak Overhead Size" );
  258. fprintf( fp, ",Time(ms)" );
  259. fprintf( fp, ",Current Count" );
  260. fprintf( fp, ",Peak Count" );
  261. fprintf( fp, ",Total Count" );
  262. fprintf( fp, ",<=16 Byte Allocations" );
  263. fprintf( fp, ",17-32 Byte Allocations" );
  264. fprintf( fp, ",33-128 Byte Allocations" );
  265. fprintf( fp, ",129-1024 Byte Allocations" );
  266. fprintf( fp, ",>1024 Byte Allocations" );
  267. fprintf( fp, "\n" );
  268. // dump to the log
  269. for ( i=0; i<g_showMemDump_numMemory; i++ )
  270. {
  271. fprintf( fp, "\"%s\"", g_showMemDump_pMemory[i].detail.pAllocationName );
  272. fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.currentSize, buff, false ) );
  273. fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakSize, buff, false ) );
  274. fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.totalSize, buff, false ) );
  275. fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.overheadSize, buff, false ) );
  276. fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakOverheadSize, buff, false ) );
  277. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.time );
  278. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.currentCount );
  279. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.peakCount );
  280. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.totalCount );
  281. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte16 );
  282. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte32 );
  283. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte128 );
  284. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte1024 );
  285. fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.gt1024 );
  286. fprintf( fp, "\n" );
  287. }
  288. fclose( fp );
  289. }
  290. //-----------------------------------------------------------------------------
  291. // ShowMemDump_Summary
  292. //
  293. //-----------------------------------------------------------------------------
  294. void ShowMemDump_Summary()
  295. {
  296. char buff[1024];
  297. int i;
  298. if ( g_showMemDump_format != FORMAT_DETAILS )
  299. {
  300. return;
  301. }
  302. int currentSize = 0;
  303. int peakSize = 0;
  304. int totalSize = 0;
  305. int overheadSize = 0;
  306. int peakOverheadSize = 0;
  307. int time = 0;
  308. int currentCount = 0;
  309. int peakCount = 0;
  310. int totalCount = 0;
  311. int lte16 = 0;
  312. int lte32 = 0;
  313. int lte128 = 0;
  314. int lte1024 = 0;
  315. int gt1024 = 0;
  316. // tally the totals
  317. for (i=0; i<g_showMemDump_numMemory; i++)
  318. {
  319. if ( !strnicmp( g_showMemDump_pMemory[i].detail.pAllocationName, "Totals,", 7 ) )
  320. continue;
  321. currentSize += g_showMemDump_pMemory[i].detail.currentSize;
  322. peakSize += g_showMemDump_pMemory[i].detail.peakSize;
  323. totalSize += g_showMemDump_pMemory[i].detail.totalSize;
  324. overheadSize += g_showMemDump_pMemory[i].detail.overheadSize;
  325. peakOverheadSize += g_showMemDump_pMemory[i].detail.peakOverheadSize;
  326. time += g_showMemDump_pMemory[i].detail.time;
  327. currentCount += g_showMemDump_pMemory[i].detail.currentCount;
  328. peakCount += g_showMemDump_pMemory[i].detail.peakCount;
  329. totalCount += g_showMemDump_pMemory[i].detail.totalCount;
  330. lte16 += g_showMemDump_pMemory[i].detail.lte16;
  331. lte32 += g_showMemDump_pMemory[i].detail.lte32;
  332. lte128 += g_showMemDump_pMemory[i].detail.lte128;
  333. lte1024 += g_showMemDump_pMemory[i].detail.lte1024;
  334. gt1024 += g_showMemDump_pMemory[i].detail.gt1024;
  335. }
  336. sprintf(
  337. buff,
  338. "Entries:\t\t\t%d\n"
  339. "Current Size:\t\t%.2f MB\n"
  340. "Peak Size:\t\t%.2f MB\n"
  341. "Total Size:\t\t%.2f MB\n"
  342. "Overhead Size:\t\t%d\n"
  343. "Peak Overhead Size:\t%d\n"
  344. "Time:\t\t\t%d\n"
  345. "Current Count:\t\t%d\n"
  346. "Peak Count:\t\t%d\n"
  347. "Total Count:\t\t%d\n"
  348. "<= 16:\t\t\t%d\n"
  349. "17-32:\t\t\t%d\n"
  350. "33-128:\t\t\t%d\n"
  351. "129-1024:\t\t%d\n"
  352. "> 1024:\t\t\t%d\n",
  353. g_showMemDump_numMemory,
  354. (float)currentSize/( 1024.0F*1024.0F ),
  355. (float)peakSize/( 1024.0F*1024.0F ),
  356. (float)totalSize/( 1024.0F*1024.0F ),
  357. overheadSize,
  358. peakOverheadSize,
  359. time,
  360. currentCount,
  361. peakCount,
  362. totalCount,
  363. lte16,
  364. lte32,
  365. lte128,
  366. lte1024,
  367. gt1024 );
  368. MessageBox( g_showMemDump_hWnd, buff, "Memory Dump Summary", MB_OK|MB_APPLMODAL );
  369. }
  370. //-----------------------------------------------------------------------------
  371. // ShowMemDump_SetTitle
  372. //
  373. //-----------------------------------------------------------------------------
  374. void ShowMemDump_SetTitle()
  375. {
  376. if ( g_showMemDump_hWnd )
  377. {
  378. SetWindowText( g_showMemDump_hWnd, "Memory Dump" );
  379. }
  380. }
  381. //-----------------------------------------------------------------------------
  382. // ShowMemDump_CompareFunc
  383. //
  384. //-----------------------------------------------------------------------------
  385. int CALLBACK ShowMemDump_CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
  386. {
  387. memory_t* pMemoryA = (memory_t*)lParam1;
  388. memory_t* pMemoryB = (memory_t*)lParam2;
  389. int sort = 0;
  390. if ( g_showMemDump_format == FORMAT_POOLS )
  391. {
  392. switch ( g_showMemDump_sortColumn )
  393. {
  394. case ID_DUMPPOOL_POOL:
  395. sort = pMemoryA->pool.pool - pMemoryB->pool.pool;
  396. break;
  397. case ID_DUMPPOOL_SIZE:
  398. sort = pMemoryA->pool.size - pMemoryB->pool.size;
  399. break;
  400. case ID_DUMPPOOL_ALLOCATED:
  401. sort = pMemoryA->pool.allocated - pMemoryB->pool.allocated;
  402. break;
  403. case ID_DUMPPOOL_FREE:
  404. sort = pMemoryA->pool.free - pMemoryB->pool.free;
  405. break;
  406. case ID_DUMPPOOL_COMMITTED:
  407. sort = pMemoryA->pool.committed - pMemoryB->pool.committed;
  408. break;
  409. case ID_DUMPPOOL_COMMITTEDSIZE:
  410. sort = pMemoryA->pool.committedSize - pMemoryB->pool.committedSize;
  411. break;
  412. }
  413. }
  414. else
  415. {
  416. switch ( g_showMemDump_sortColumn )
  417. {
  418. case ID_DUMPDETAIL_ALLOCATION:
  419. sort = stricmp( pMemoryA->detail.pAllocationName, pMemoryB->detail.pAllocationName );
  420. break;
  421. case ID_DUMPDETAIL_CURRENTSIZE:
  422. sort = pMemoryA->detail.currentSize - pMemoryB->detail.currentSize;
  423. break;
  424. case ID_DUMPDETAIL_PEAKSIZE:
  425. sort = pMemoryA->detail.peakSize - pMemoryB->detail.peakSize;
  426. break;
  427. case ID_DUMPDETAIL_TOTALSIZE:
  428. sort = pMemoryA->detail.totalSize - pMemoryB->detail.totalSize;
  429. break;
  430. case ID_DUMPDETAIL_OVERHEAD:
  431. sort = pMemoryA->detail.overheadSize - pMemoryB->detail.overheadSize;
  432. break;
  433. case ID_DUMPDETAIL_PEAKOVERHEAD:
  434. sort = pMemoryA->detail.peakOverheadSize - pMemoryB->detail.peakOverheadSize;
  435. break;
  436. case ID_DUMPDETAIL_TIME:
  437. sort = pMemoryA->detail.time - pMemoryB->detail.time;
  438. break;
  439. case ID_DUMPDETAIL_CURRENTCOUNT:
  440. sort = pMemoryA->detail.currentCount - pMemoryB->detail.currentCount;
  441. break;
  442. case ID_DUMPDETAIL_PEAKCOUNT:
  443. sort = pMemoryA->detail.peakCount - pMemoryB->detail.peakCount;
  444. break;
  445. case ID_DUMPDETAIL_TOTALCOUNT:
  446. sort = pMemoryA->detail.totalCount - pMemoryB->detail.totalCount;
  447. break;
  448. case ID_DUMPDETAIL_LTE16:
  449. sort = pMemoryA->detail.lte16 - pMemoryB->detail.lte16;
  450. break;
  451. case ID_DUMPDETAIL_LTE32:
  452. sort = pMemoryA->detail.lte32 - pMemoryB->detail.lte32;
  453. break;
  454. case ID_DUMPDETAIL_LTE128:
  455. sort = pMemoryA->detail.lte128 - pMemoryB->detail.lte128;
  456. break;
  457. case ID_DUMPDETAIL_LTE1024:
  458. sort = pMemoryA->detail.lte1024 - pMemoryB->detail.lte1024;
  459. break;
  460. case ID_DUMPDETAIL_GT1024:
  461. sort = pMemoryA->detail.gt1024 - pMemoryB->detail.gt1024;
  462. break;
  463. }
  464. }
  465. // flip the sort order
  466. if ( g_showMemDump_sortDescending )
  467. {
  468. sort *= -1;
  469. }
  470. return ( sort );
  471. }
  472. //-----------------------------------------------------------------------------
  473. // ShowMemDump_SortItems
  474. //
  475. //-----------------------------------------------------------------------------
  476. void ShowMemDump_SortItems()
  477. {
  478. LVITEM lvitem;
  479. memory_t *pMemory;
  480. int i;
  481. if ( !g_showMemDump_hWnd )
  482. {
  483. // only sort if window is visible
  484. return;
  485. }
  486. ListView_SortItems( g_showMemDump_hWndListView, ShowMemDump_CompareFunc, 0 );
  487. memset( &lvitem, 0, sizeof( lvitem ) );
  488. lvitem.mask = LVIF_PARAM;
  489. // get each item and reset its list index
  490. int itemCount = ListView_GetItemCount( g_showMemDump_hWndListView );
  491. for ( i=0; i<itemCount; i++ )
  492. {
  493. lvitem.iItem = i;
  494. ListView_GetItem( g_showMemDump_hWndListView, &lvitem );
  495. pMemory = (memory_t*)lvitem.lParam;
  496. pMemory->listIndex = i;
  497. }
  498. int count;
  499. label_t* pLabels;
  500. if ( g_showMemDump_format == FORMAT_POOLS )
  501. {
  502. count = sizeof( g_showMemDump_PoolLabels )/sizeof( g_showMemDump_PoolLabels[0] );
  503. pLabels = g_showMemDump_PoolLabels;
  504. }
  505. else
  506. {
  507. count = sizeof( g_showMemDump_DetailLabels )/sizeof( g_showMemDump_DetailLabels[0] );
  508. pLabels = g_showMemDump_DetailLabels;
  509. }
  510. // update list view columns with sort key
  511. for ( i = 0; i < count; i++ )
  512. {
  513. char symbol;
  514. LVCOLUMN lvc;
  515. if ( i == g_showMemDump_sortColumn )
  516. symbol = g_showMemDump_sortDescending ? '<' : '>';
  517. else
  518. symbol = ' ';
  519. sprintf( pLabels[i].nameBuff, "%s %c", pLabels[i].name, symbol );
  520. memset( &lvc, 0, sizeof( lvc ) );
  521. lvc.mask = LVCF_TEXT;
  522. lvc.pszText = (LPSTR)pLabels[i].nameBuff;
  523. ListView_SetColumn( g_showMemDump_hWndListView, i, &lvc );
  524. }
  525. }
  526. //-----------------------------------------------------------------------------
  527. // ShowMemDump_FormatItems
  528. //
  529. //-----------------------------------------------------------------------------
  530. void ShowMemDump_FormatItems()
  531. {
  532. if ( g_showMemDump_format == FORMAT_POOLS )
  533. {
  534. for ( int i = 0; i < g_showMemDump_numMemory; i++ )
  535. {
  536. sprintf( g_showMemDump_pMemory[i].pool.sizeBuff, "%d", g_showMemDump_pMemory[i].pool.size );
  537. ShowMemDump_FormatSize( g_showMemDump_pMemory[i].pool.committedSize, g_showMemDump_pMemory[i].pool.committedSizeBuff, true );
  538. }
  539. }
  540. else
  541. {
  542. for ( int i = 0; i < g_showMemDump_numMemory; i++ )
  543. {
  544. ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.currentSize, g_showMemDump_pMemory[i].detail.currentSizeBuff, true );
  545. ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakSize, g_showMemDump_pMemory[i].detail.peakSizeBuff, true );
  546. ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.totalSize, g_showMemDump_pMemory[i].detail.totalSizeBuff, true );
  547. ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.overheadSize, g_showMemDump_pMemory[i].detail.overheadSizeBuff, true );
  548. ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakOverheadSize, g_showMemDump_pMemory[i].detail.peakOverheadSizeBuff, true );
  549. }
  550. }
  551. ShowMemDump_SortItems();
  552. }
  553. //-----------------------------------------------------------------------------
  554. // ShowMemDump_AddViewItem
  555. //
  556. //-----------------------------------------------------------------------------
  557. void ShowMemDump_AddViewItem( memory_t* pMemory )
  558. {
  559. LVITEM lvi;
  560. if ( !g_showMemDump_hWnd )
  561. {
  562. // only valid if log window is visible
  563. return;
  564. }
  565. // update the text callback buffers
  566. if ( g_showMemDump_format == FORMAT_POOLS )
  567. {
  568. sprintf( pMemory->pool.sizeBuff, "%d", pMemory->pool.size );
  569. sprintf( pMemory->pool.poolBuff, "%d", pMemory->pool.pool );
  570. sprintf( pMemory->pool.allocatedBuff, "%d", pMemory->pool.allocated );
  571. sprintf( pMemory->pool.freeBuff, "%d", pMemory->pool.free );
  572. sprintf( pMemory->pool.committedBuff, "%d", pMemory->pool.committed );
  573. ShowMemDump_FormatSize( pMemory->pool.committedSize, pMemory->pool.committedSizeBuff, true );
  574. }
  575. else
  576. {
  577. ShowMemDump_FormatSize( pMemory->detail.currentSize, pMemory->detail.currentSizeBuff, true );
  578. ShowMemDump_FormatSize( pMemory->detail.peakSize, pMemory->detail.peakSizeBuff, true );
  579. ShowMemDump_FormatSize( pMemory->detail.totalSize, pMemory->detail.totalSizeBuff, true );
  580. ShowMemDump_FormatSize( pMemory->detail.overheadSize, pMemory->detail.overheadSizeBuff, true );
  581. ShowMemDump_FormatSize( pMemory->detail.peakOverheadSize, pMemory->detail.peakOverheadSizeBuff, true );
  582. sprintf( pMemory->detail.timeBuff, "%d", pMemory->detail.time );
  583. sprintf( pMemory->detail.currentCountBuff, "%d", pMemory->detail.currentCount );
  584. sprintf( pMemory->detail.peakCountBuff, "%d", pMemory->detail.peakCount );
  585. sprintf( pMemory->detail.totalCountBuff, "%d", pMemory->detail.totalCount );
  586. sprintf( pMemory->detail.lte16Buff, "%d", pMemory->detail.lte16 );
  587. sprintf( pMemory->detail.lte32Buff, "%d", pMemory->detail.lte32 );
  588. sprintf( pMemory->detail.lte128Buff, "%d", pMemory->detail.lte128 );
  589. sprintf( pMemory->detail.lte1024Buff, "%d", pMemory->detail.lte1024 );
  590. sprintf( pMemory->detail.gt1024Buff, "%d", pMemory->detail.gt1024 );
  591. }
  592. int itemCount = ListView_GetItemCount( g_showMemDump_hWndListView );
  593. // setup and insert at end of list
  594. memset( &lvi, 0, sizeof( lvi ) );
  595. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  596. lvi.iItem = itemCount;
  597. lvi.iSubItem = 0;
  598. lvi.state = 0;
  599. lvi.stateMask = 0;
  600. lvi.pszText = LPSTR_TEXTCALLBACK;
  601. lvi.lParam = (LPARAM)pMemory;
  602. // insert and set the real index
  603. pMemory->listIndex = ListView_InsertItem( g_showMemDump_hWndListView, &lvi );
  604. }
  605. //-----------------------------------------------------------------------------
  606. // ShowMemDump_Refresh
  607. //
  608. //-----------------------------------------------------------------------------
  609. void ShowMemDump_Refresh()
  610. {
  611. // send the command to application which replies with list data
  612. if ( g_connectedToApp )
  613. {
  614. ProcessCommand( "mem_dump" );
  615. }
  616. }
  617. //-----------------------------------------------------------------------------
  618. // ShowMemDump_RefreshView
  619. //
  620. //-----------------------------------------------------------------------------
  621. void ShowMemDump_RefreshView()
  622. {
  623. if ( strlen( g_showMemDump_currentFilename ) == 0 )
  624. {
  625. // first time
  626. ShowMemDump_Refresh();
  627. return;
  628. }
  629. // get current file
  630. int fileSize;
  631. char *pBuffer;
  632. bool bSuccess = LoadTargetFile( g_showMemDump_currentFilename, &fileSize, (void **)&pBuffer );
  633. if ( !bSuccess )
  634. {
  635. // stale, try again
  636. ShowMemDump_Refresh();
  637. return;
  638. }
  639. // parse and update view
  640. ShowMemDump_Parse( pBuffer, fileSize );
  641. Sys_Free( pBuffer );
  642. }
  643. //-----------------------------------------------------------------------------
  644. // ShowMemDump_PopulateList
  645. //
  646. //-----------------------------------------------------------------------------
  647. void ShowMemDump_PopulateList()
  648. {
  649. // delete previous labels
  650. while ( 1 )
  651. {
  652. if ( !ListView_DeleteColumn( g_showMemDump_hWndListView, 0 ) )
  653. {
  654. break;
  655. }
  656. }
  657. int count;
  658. label_t* pLabels;
  659. if ( g_showMemDump_format == FORMAT_POOLS )
  660. {
  661. count = sizeof( g_showMemDump_PoolLabels )/sizeof( g_showMemDump_PoolLabels[0] );
  662. pLabels = g_showMemDump_PoolLabels;
  663. }
  664. else
  665. {
  666. count = sizeof( g_showMemDump_DetailLabels )/sizeof( g_showMemDump_DetailLabels[0] );
  667. pLabels = g_showMemDump_DetailLabels;
  668. }
  669. // init list view columns
  670. for ( int i = 0; i < count; i++ )
  671. {
  672. LVCOLUMN lvc;
  673. memset( &lvc, 0, sizeof( lvc ) );
  674. lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
  675. lvc.iSubItem = 0;
  676. lvc.cx = pLabels[i].width;
  677. lvc.fmt = LVCFMT_LEFT;
  678. lvc.pszText = ( LPSTR )pLabels[i].name;
  679. ListView_InsertColumn( g_showMemDump_hWndListView, i, &lvc );
  680. }
  681. // populate list view
  682. for ( int i = 0; i < g_showMemDump_numMemory; i++ )
  683. {
  684. ShowMemDump_AddViewItem( &g_showMemDump_pMemory[i] );
  685. }
  686. ShowMemDump_SortItems();
  687. }
  688. //-----------------------------------------------------------------------------
  689. // ShowMemDump_SizeWindow
  690. //
  691. //-----------------------------------------------------------------------------
  692. void ShowMemDump_SizeWindow( HWND hwnd, int cx, int cy )
  693. {
  694. if ( cx==0 || cy==0 )
  695. {
  696. RECT rcClient;
  697. GetClientRect( hwnd, &rcClient );
  698. cx = rcClient.right;
  699. cy = rcClient.bottom;
  700. }
  701. // position the ListView
  702. SetWindowPos( g_showMemDump_hWndListView, NULL, 0, 0, cx, cy, SWP_NOZORDER );
  703. }
  704. //-----------------------------------------------------------------------------
  705. // ShowMemDump_WndProc
  706. //
  707. //-----------------------------------------------------------------------------
  708. LRESULT CALLBACK ShowMemDump_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
  709. {
  710. WORD wID = LOWORD( wParam );
  711. memory_t* pMemory;
  712. switch ( message )
  713. {
  714. case WM_CREATE:
  715. return 0L;
  716. case WM_DESTROY:
  717. ShowMemDump_SaveConfig();
  718. g_showMemDump_hWnd = NULL;
  719. return 0L;
  720. case WM_INITMENU:
  721. CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_BYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_BYTES ? MF_CHECKED : MF_UNCHECKED ) );
  722. CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_KILOBYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_KILOBYTES ? MF_CHECKED : MF_UNCHECKED ) );
  723. CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_MEGABYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_MEGABYTES ? MF_CHECKED : MF_UNCHECKED ) );
  724. CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_COLLAPSEOUTPUT, MF_BYCOMMAND | ( g_showMemDump_bCollapseOutput ? MF_CHECKED : MF_UNCHECKED ) );
  725. return 0L;
  726. case WM_SIZE:
  727. ShowMemDump_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) );
  728. return 0L;
  729. case WM_NOTIFY:
  730. switch ( ( ( LPNMHDR )lParam )->code )
  731. {
  732. case LVN_COLUMNCLICK:
  733. NMLISTVIEW* pnmlv;
  734. pnmlv = ( NMLISTVIEW* )lParam;
  735. if ( g_showMemDump_sortColumn == pnmlv->iSubItem )
  736. {
  737. // user has clicked on same column - flip the sort
  738. g_showMemDump_sortDescending ^= 1;
  739. }
  740. else
  741. {
  742. // sort by new column
  743. g_showMemDump_sortColumn = pnmlv->iSubItem;
  744. }
  745. ShowMemDump_SortItems();
  746. return 0L;
  747. case LVN_GETDISPINFO:
  748. NMLVDISPINFO* plvdi;
  749. plvdi = (NMLVDISPINFO*)lParam;
  750. pMemory = (memory_t*)plvdi->item.lParam;
  751. if ( g_showMemDump_format == FORMAT_POOLS )
  752. {
  753. switch ( plvdi->item.iSubItem )
  754. {
  755. case ID_DUMPPOOL_POOL:
  756. plvdi->item.pszText = pMemory->pool.poolBuff;
  757. return 0L;
  758. case ID_DUMPPOOL_SIZE:
  759. plvdi->item.pszText = pMemory->pool.sizeBuff;
  760. return 0L;
  761. case ID_DUMPPOOL_ALLOCATED:
  762. plvdi->item.pszText = pMemory->pool.allocatedBuff;
  763. return 0L;
  764. case ID_DUMPPOOL_FREE:
  765. plvdi->item.pszText = pMemory->pool.freeBuff;
  766. return 0L;
  767. case ID_DUMPPOOL_COMMITTED:
  768. plvdi->item.pszText = pMemory->pool.committedBuff;
  769. return 0L;
  770. case ID_DUMPPOOL_COMMITTEDSIZE:
  771. plvdi->item.pszText = pMemory->pool.committedSizeBuff;
  772. return 0L;
  773. }
  774. }
  775. else
  776. {
  777. switch ( plvdi->item.iSubItem )
  778. {
  779. case ID_DUMPDETAIL_ALLOCATION:
  780. plvdi->item.pszText = pMemory->detail.pAllocationName;
  781. return 0L;
  782. case ID_DUMPDETAIL_CURRENTSIZE:
  783. plvdi->item.pszText = pMemory->detail.currentSizeBuff;
  784. return 0L;
  785. case ID_DUMPDETAIL_PEAKSIZE:
  786. plvdi->item.pszText = pMemory->detail.peakSizeBuff;
  787. return 0L;
  788. case ID_DUMPDETAIL_TOTALSIZE:
  789. plvdi->item.pszText = pMemory->detail.totalSizeBuff;
  790. return 0L;
  791. case ID_DUMPDETAIL_OVERHEAD:
  792. plvdi->item.pszText = pMemory->detail.overheadSizeBuff;
  793. return 0L;
  794. case ID_DUMPDETAIL_PEAKOVERHEAD:
  795. plvdi->item.pszText = pMemory->detail.peakOverheadSizeBuff;
  796. return 0L;
  797. case ID_DUMPDETAIL_TIME:
  798. plvdi->item.pszText = pMemory->detail.timeBuff;
  799. return 0L;
  800. case ID_DUMPDETAIL_CURRENTCOUNT:
  801. plvdi->item.pszText = pMemory->detail.currentCountBuff;
  802. return 0L;
  803. case ID_DUMPDETAIL_PEAKCOUNT:
  804. plvdi->item.pszText = pMemory->detail.peakCountBuff;
  805. return 0L;
  806. case ID_DUMPDETAIL_TOTALCOUNT:
  807. plvdi->item.pszText = pMemory->detail.totalCountBuff;
  808. return 0L;
  809. case ID_DUMPDETAIL_LTE16:
  810. plvdi->item.pszText = pMemory->detail.lte16Buff;
  811. return 0L;
  812. case ID_DUMPDETAIL_LTE32:
  813. plvdi->item.pszText = pMemory->detail.lte32Buff;
  814. return 0L;
  815. case ID_DUMPDETAIL_LTE128:
  816. plvdi->item.pszText = pMemory->detail.lte128Buff;
  817. return 0L;
  818. case ID_DUMPDETAIL_LTE1024:
  819. plvdi->item.pszText = pMemory->detail.lte1024Buff;
  820. return 0L;
  821. case ID_DUMPDETAIL_GT1024:
  822. plvdi->item.pszText = pMemory->detail.gt1024Buff;
  823. return 0L;
  824. default:
  825. break;
  826. }
  827. }
  828. break;
  829. }
  830. break;
  831. case WM_COMMAND:
  832. switch ( wID )
  833. {
  834. case IDM_OPTIONS_REFRESH:
  835. ShowMemDump_Refresh();
  836. return 0L;
  837. case IDM_OPTIONS_EXPORT:
  838. ShowMemDump_Export();
  839. return 0L;
  840. case IDM_OPTIONS_SUMMARY:
  841. ShowMemDump_Summary();
  842. return 0L;
  843. case IDM_OPTIONS_BYTES:
  844. g_showMemDump_showBytes = SHOW_BYTES;
  845. ShowMemDump_FormatItems();
  846. return 0L;
  847. case IDM_OPTIONS_KILOBYTES:
  848. g_showMemDump_showBytes = SHOW_KILOBYTES;
  849. ShowMemDump_FormatItems();
  850. return 0L;
  851. case IDM_OPTIONS_MEGABYTES:
  852. g_showMemDump_showBytes = SHOW_MEGABYTES;
  853. ShowMemDump_FormatItems();
  854. return 0L;
  855. case IDM_OPTIONS_COLLAPSEOUTPUT:
  856. g_showMemDump_bCollapseOutput = !g_showMemDump_bCollapseOutput;
  857. ShowMemDump_RefreshView();
  858. return 0L;
  859. }
  860. break;
  861. }
  862. return ( DefWindowProc( hwnd, message, wParam, lParam ) );
  863. }
  864. //-----------------------------------------------------------------------------
  865. // ShowMemDump_Init
  866. //
  867. //-----------------------------------------------------------------------------
  868. bool ShowMemDump_Init()
  869. {
  870. // set up our window class
  871. WNDCLASS wndclass;
  872. memset( &wndclass, 0, sizeof( wndclass ) );
  873. wndclass.style = 0;
  874. wndclass.lpfnWndProc = ShowMemDump_WndProc;
  875. wndclass.cbClsExtra = 0;
  876. wndclass.cbWndExtra = 0;
  877. wndclass.hInstance = g_hInstance;
  878. wndclass.hIcon = g_hIcons[ICON_APPLICATION];
  879. wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
  880. wndclass.hbrBackground = g_hBackgroundBrush;
  881. wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_SHOWMEMORYDUMP );
  882. wndclass.lpszClassName = "SHOWMEMDUMPCLASS";
  883. if ( !RegisterClass( &wndclass ) )
  884. return false;
  885. ShowMemDump_LoadConfig();
  886. return true;
  887. }
  888. //-----------------------------------------------------------------------------
  889. // ShowMemDump_Open
  890. //
  891. //-----------------------------------------------------------------------------
  892. void ShowMemDump_Open()
  893. {
  894. RECT clientRect;
  895. HWND hWnd;
  896. if ( g_showMemDump_hWnd )
  897. {
  898. // only one instance
  899. if ( IsIconic( g_showMemDump_hWnd ) )
  900. ShowWindow( g_showMemDump_hWnd, SW_RESTORE );
  901. SetForegroundWindow( g_showMemDump_hWnd );
  902. return;
  903. }
  904. hWnd = CreateWindowEx(
  905. WS_EX_CLIENTEDGE,
  906. "SHOWMEMDUMPCLASS",
  907. "",
  908. WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
  909. 0,
  910. 0,
  911. 700,
  912. 400,
  913. g_hDlgMain,
  914. NULL,
  915. g_hInstance,
  916. NULL );
  917. g_showMemDump_hWnd = hWnd;
  918. GetClientRect( g_showMemDump_hWnd, &clientRect );
  919. hWnd = CreateWindow(
  920. WC_LISTVIEW,
  921. "",
  922. WS_VISIBLE|WS_CHILD|LVS_REPORT,
  923. 0,
  924. 0,
  925. clientRect.right-clientRect.left,
  926. clientRect.bottom-clientRect.top,
  927. g_showMemDump_hWnd,
  928. ( HMENU )ID_SHOWMEMDUMP_LISTVIEW,
  929. g_hInstance,
  930. NULL );
  931. g_showMemDump_hWndListView = hWnd;
  932. ListView_SetBkColor( g_showMemDump_hWndListView, g_backgroundColor );
  933. ListView_SetTextBkColor( g_showMemDump_hWndListView, g_backgroundColor );
  934. DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP;
  935. ListView_SetExtendedListViewStyleEx( g_showMemDump_hWndListView, style, style );
  936. ShowMemDump_PopulateList();
  937. ShowMemDump_SetTitle();
  938. if ( g_showMemDump_windowRect.right && g_showMemDump_windowRect.bottom )
  939. MoveWindow( g_showMemDump_hWnd, g_showMemDump_windowRect.left, g_showMemDump_windowRect.top, g_showMemDump_windowRect.right-g_showMemDump_windowRect.left, g_showMemDump_windowRect.bottom-g_showMemDump_windowRect.top, FALSE );
  940. ShowWindow( g_showMemDump_hWnd, SHOW_OPENWINDOW );
  941. // get data from application
  942. ShowMemDump_Refresh();
  943. }
  944. //-----------------------------------------------------------------------------
  945. // MatchAllocationName
  946. //
  947. //-----------------------------------------------------------------------------
  948. void MatchAllocationName( memory_t *&pMemory )
  949. {
  950. memory_t *curEntry = g_showMemDump_pMemory;
  951. for ( int i=0; i<g_showMemDump_numMemory; ++i )
  952. {
  953. if ( !strcmp( curEntry->detail.pAllocationName, pMemory->detail.pAllocationName ) )
  954. {
  955. pMemory = curEntry;
  956. return;
  957. }
  958. ++curEntry;
  959. }
  960. }
  961. //-----------------------------------------------------------------------------
  962. // ShowMemDump_Parse
  963. //
  964. //-----------------------------------------------------------------------------
  965. void ShowMemDump_Parse( const char *pBuffer, int fileSize )
  966. {
  967. char *ptr;
  968. char *pToken;
  969. char *pLineStart;
  970. int numLines;
  971. int size;
  972. memory_t *pMemory;
  973. // remove old entries
  974. ShowMemDump_Clear();
  975. if ( !pBuffer || !fileSize )
  976. {
  977. // no valid data
  978. return;
  979. }
  980. Sys_SetScriptData( pBuffer, fileSize );
  981. // skip first line, column headers
  982. Sys_SkipRestOfLine();
  983. Sys_SaveParser();
  984. // count lines
  985. numLines = 0;
  986. while ( 1 )
  987. {
  988. pToken = Sys_GetToken( true );
  989. if ( !pToken || !pToken[0] )
  990. break;
  991. numLines++;
  992. Sys_SkipRestOfLine();
  993. }
  994. // each line represents one complete entry
  995. g_showMemDump_pMemory = (memory_t *)Sys_Alloc( numLines * sizeof( memory_t ) );
  996. Sys_RestoreParser();
  997. pMemory = g_showMemDump_pMemory;
  998. int format = 0;
  999. if ( !V_strnicmp( g_sys_scriptptr, "pool ", 5 ) )
  1000. {
  1001. // parse as pool stats
  1002. format = FORMAT_POOLS;
  1003. while ( 1 )
  1004. {
  1005. // find start of relevant data
  1006. bool bFound = false;
  1007. while ( 1 )
  1008. {
  1009. pToken = Sys_GetToken( true );
  1010. if ( !pToken || !pToken[0] )
  1011. break;
  1012. if ( !V_stricmp( pToken, "size:" ) )
  1013. {
  1014. bFound = true;
  1015. break;
  1016. }
  1017. }
  1018. if ( !bFound )
  1019. {
  1020. break;
  1021. }
  1022. memset( pMemory, 0, sizeof( memory_t ) );
  1023. pMemory->pool.pool = g_showMemDump_numMemory;
  1024. pToken = Sys_GetToken( false );
  1025. if ( !pToken || !pToken[0] )
  1026. break;
  1027. pMemory->pool.size = atoi( pToken );
  1028. pToken = Sys_GetToken( false );
  1029. if ( !pToken || !pToken[0] )
  1030. break;
  1031. if ( !V_stricmp( pToken, "allocated:" ) )
  1032. {
  1033. pToken = Sys_GetToken( false );
  1034. if ( !pToken || !pToken[0] )
  1035. break;
  1036. pMemory->pool.allocated = atoi( pToken );
  1037. }
  1038. else
  1039. {
  1040. break;
  1041. }
  1042. pToken = Sys_GetToken( false );
  1043. if ( !pToken || !pToken[0] )
  1044. break;
  1045. if ( !V_stricmp( pToken, "free:" ) )
  1046. {
  1047. pToken = Sys_GetToken( false );
  1048. if ( !pToken || !pToken[0] )
  1049. break;
  1050. pMemory->pool.free = atoi( pToken );
  1051. }
  1052. else
  1053. {
  1054. break;
  1055. }
  1056. pToken = Sys_GetToken( false );
  1057. if ( !pToken || !pToken[0] )
  1058. break;
  1059. if ( !V_stricmp( pToken, "committed:" ) )
  1060. {
  1061. pToken = Sys_GetToken( false );
  1062. if ( !pToken || !pToken[0] )
  1063. break;
  1064. pMemory->pool.committed = atoi( pToken );
  1065. }
  1066. else
  1067. {
  1068. break;
  1069. }
  1070. pToken = Sys_GetToken( false );
  1071. if ( !pToken || !pToken[0] )
  1072. break;
  1073. if ( !V_stricmp( pToken, "committedsize:" ) )
  1074. {
  1075. pToken = Sys_GetToken( false );
  1076. if ( !pToken || !pToken[0] )
  1077. break;
  1078. pMemory->pool.committedSize = atoi( pToken );
  1079. }
  1080. else
  1081. {
  1082. break;
  1083. }
  1084. pMemory++;
  1085. g_showMemDump_numMemory++;
  1086. if ( g_showMemDump_numMemory >= numLines )
  1087. break;
  1088. }
  1089. }
  1090. else
  1091. {
  1092. // parse as detail stats
  1093. format = FORMAT_DETAILS;
  1094. while ( 1 )
  1095. {
  1096. pLineStart = g_sys_scriptptr;
  1097. // can't tokenize, find start of parsable data
  1098. ptr = V_stristr( g_sys_scriptptr, ", line " );
  1099. if ( !ptr )
  1100. break;
  1101. g_sys_scriptptr = ptr + strlen( ", line " );
  1102. // advance past the expected line number
  1103. pToken = Sys_GetToken( false );
  1104. if ( !pToken || !pToken[0] )
  1105. break;
  1106. if ( !g_showMemDump_bCollapseOutput )
  1107. {
  1108. size = g_sys_scriptptr-pLineStart;
  1109. }
  1110. else
  1111. {
  1112. size = ptr-pLineStart;
  1113. }
  1114. memset( pMemory, 0, sizeof(memory_t) );
  1115. memory_t *pCurRecordStart = pMemory;
  1116. pMemory->detail.pAllocationName = new char[size+1];
  1117. memcpy( pMemory->detail.pAllocationName, pLineStart, size );
  1118. pMemory->detail.pAllocationName[size] = '\0';
  1119. Sys_NormalizePath( pMemory->detail.pAllocationName, false );
  1120. if ( g_showMemDump_bCollapseOutput )
  1121. {
  1122. MatchAllocationName( pMemory );
  1123. }
  1124. pToken = Sys_GetToken( false );
  1125. if ( !pToken || !pToken[0] )
  1126. break;
  1127. pMemory->detail.currentSize += (int)(1024.0f*atof( pToken ));
  1128. pToken = Sys_GetToken( false );
  1129. if ( !pToken || !pToken[0] )
  1130. break;
  1131. pMemory->detail.peakSize += (int)(1024.0f*atof( pToken ));
  1132. pToken = Sys_GetToken( false );
  1133. if ( !pToken || !pToken[0] )
  1134. break;
  1135. pMemory->detail.totalSize += (int)(1024.0f*atof( pToken ));
  1136. pToken = Sys_GetToken( false );
  1137. if ( !pToken || !pToken[0] )
  1138. break;
  1139. pMemory->detail.overheadSize += (int)(1024.0f*atof( pToken ));
  1140. pToken = Sys_GetToken( false );
  1141. if ( !pToken || !pToken[0] )
  1142. break;
  1143. pMemory->detail.peakOverheadSize += (int)(1024.0f*atof( pToken ));
  1144. pToken = Sys_GetToken( false );
  1145. if ( !pToken || !pToken[0] )
  1146. break;
  1147. pMemory->detail.time += atoi( pToken );
  1148. pToken = Sys_GetToken( false );
  1149. if ( !pToken || !pToken[0] )
  1150. break;
  1151. pMemory->detail.currentCount += atoi( pToken );
  1152. pToken = Sys_GetToken( false );
  1153. if ( !pToken || !pToken[0] )
  1154. break;
  1155. pMemory->detail.peakCount += atoi( pToken );
  1156. pToken = Sys_GetToken( false );
  1157. if ( !pToken || !pToken[0] )
  1158. break;
  1159. pMemory->detail.totalCount += atoi( pToken );
  1160. pToken = Sys_GetToken( false );
  1161. if ( !pToken || !pToken[0] )
  1162. break;
  1163. pMemory->detail.lte16 += atoi( pToken );
  1164. pToken = Sys_GetToken( false );
  1165. if ( !pToken || !pToken[0] )
  1166. break;
  1167. pMemory->detail.lte32 += atoi( pToken );
  1168. pToken = Sys_GetToken( false );
  1169. if ( !pToken || !pToken[0] )
  1170. break;
  1171. pMemory->detail.lte128 += atoi( pToken );
  1172. pToken = Sys_GetToken( false );
  1173. if ( !pToken || !pToken[0] )
  1174. break;
  1175. pMemory->detail.lte1024 += atoi( pToken );
  1176. pToken = Sys_GetToken( false );
  1177. if ( !pToken || !pToken[0] )
  1178. break;
  1179. pMemory->detail.gt1024 += atoi( pToken );
  1180. Sys_SkipRestOfLine();
  1181. if( pMemory == pCurRecordStart )
  1182. {
  1183. pMemory++;
  1184. g_showMemDump_numMemory++;
  1185. }
  1186. else
  1187. {
  1188. pMemory = pCurRecordStart;
  1189. }
  1190. if ( g_showMemDump_numMemory >= numLines )
  1191. break;
  1192. }
  1193. }
  1194. if ( g_showMemDump_format != format )
  1195. {
  1196. // format change will cause list view change
  1197. g_showMemDump_format = format;
  1198. g_showMemDump_sortColumn = 0;
  1199. g_showMemDump_sortDescending = 0;
  1200. }
  1201. ShowMemDump_PopulateList();
  1202. }
  1203. //-----------------------------------------------------------------------------
  1204. // rc_MemDump
  1205. //
  1206. // Sent from application with memory dump file
  1207. //-----------------------------------------------------------------------------
  1208. int rc_MemDump( char *pCommand )
  1209. {
  1210. char* pToken;
  1211. int retVal;
  1212. int errCode = -1;
  1213. int fileSize;
  1214. char *pBuffer;
  1215. // get name of file
  1216. pToken = GetToken( &pCommand );
  1217. if ( !pToken[0] )
  1218. goto cleanUp;
  1219. // get file
  1220. strcpy( g_showMemDump_currentFilename, pToken );
  1221. retVal = LoadTargetFile( g_showMemDump_currentFilename, &fileSize, (void **)&pBuffer );
  1222. DebugCommand( "0x%8.8x = MemDump( %s )\n", retVal, g_showMemDump_currentFilename );
  1223. // parse and update view
  1224. ShowMemDump_Parse( pBuffer, fileSize );
  1225. Sys_Free( pBuffer );
  1226. // success
  1227. errCode = 0;
  1228. cleanUp:
  1229. return ( errCode );
  1230. }