Leaked source code of windows server 2003
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.

2027 lines
67 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * **************************
  4. * * SAMPLE CODE *
  5. * **************************
  6. *
  7. * Module Name: debug.c
  8. *
  9. * Content: Debugging aids
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. // Debug routines
  15. #include "glint.h"
  16. #include "dma.h"
  17. #include <windef.h>
  18. #include <limits.h>
  19. #include <stdio.h>
  20. #include <stdarg.h>
  21. #if DBG
  22. #if DBG_TRACK_CODE
  23. // we don't want to ever do code coverage of the debugging tools
  24. // (otherwise we might loop forever)
  25. #undef if
  26. #undef while
  27. #endif // DBG_TRACK_CODE
  28. #if DBG_TRACK_FUNCS || DBG_TRACK_CODE
  29. // Common helper functions
  30. //-----------------------------------------------------------------------------
  31. // __ShortFileName
  32. //
  33. // Leave just an 8.3 filename to store rather than a full path name
  34. //
  35. //-----------------------------------------------------------------------------
  36. char *
  37. __ShortFileName(char *pInStr)
  38. {
  39. char *pShortFN;
  40. pShortFN = pInStr;
  41. if (pInStr != NULL)
  42. {
  43. while (*pInStr != '\0')
  44. {
  45. if (*pInStr++ == '\\')
  46. {
  47. pShortFN = pInStr;
  48. }
  49. }
  50. }
  51. return (pShortFN);
  52. } // __ShortFileName
  53. #endif // DBG_TRACK_FUNCS || DBG_TRACK_CODE
  54. #if DBG_TRACK_FUNCS
  55. //-----------------------------------------------------------------------------
  56. //
  57. // ****************** FUNCTION COVERAGE DEBUGGING SUPPORT ********************
  58. //
  59. //-----------------------------------------------------------------------------
  60. //
  61. // This mechanism enables us to track which functions are called (entered),
  62. // how many times they are called, what values do they return (and if they exit
  63. // through all expected return points). Support to track maximum, minimum and
  64. // average time per call can also be implemented.
  65. //
  66. // To use it, add the DBG_ENTRY macro at the start of important functions you
  67. // want to track and before taking any return statement, add a DBG_EXIT macro
  68. // giving a DWORD value representative of the return value of the function.
  69. // Different return values will be tracked independently.
  70. //
  71. //
  72. // ********** This support should only be enabled for test runs. **********
  73. // ** IT SHOULD NOT BE SET BY DEFAULT ON NEITHER ON FREE OR CHECKED BUILDS **
  74. //
  75. //-----------------------------------------------------------------------------
  76. // Maximum of functions to be tracked. Code will take care of not exceeding
  77. // this, but it should be adjusted upward if necessary.
  78. #define DEBUG_MAX_FUNC_COUNT 200
  79. // Maximum of different return values to keep track of. Can be independent
  80. // of DEBUG_MAX_FUNC_COUNT, just using a heuristic here instead of a wild guess.
  81. #define DEBUG_MAX_RETVALS (DEBUG_MAX_FUNC_COUNT * 30)
  82. // global structures that will hold our data
  83. struct {
  84. VOID *pFuncAddr; //
  85. DWORD dwRetVal; //
  86. DWORD dwLine; //
  87. DWORD dwCount; //
  88. } g_DbgFuncRetVal[DEBUG_MAX_RETVALS];
  89. struct {
  90. VOID *pFuncAddr; //
  91. char *pszFuncName; //
  92. char *pszFileName; //
  93. DWORD dwLine; //
  94. DWORD dwEntryCount; //
  95. DWORD dwExitCount; //
  96. DWORD dwIndxLastRetVal; //
  97. // profiling support - not yet implemented //azn
  98. LONGLONG LastStartTime; //
  99. DWORD MinTime; //
  100. DWORD MaxTime; //
  101. DWORD AvgTime; //
  102. } g_DbgFuncCoverage[DEBUG_MAX_FUNC_COUNT];
  103. DWORD g_dwRetVal_Cnt = 0;
  104. DWORD g_dwFuncCov_Cnt = 0;
  105. DWORD g_dwFuncCov_Extra = 0;
  106. //-----------------------------------------------------------------------------
  107. // __Find
  108. //
  109. // Does a binary search on the g_DbgFuncCoverage array
  110. //
  111. // Since 0 is a valid array element, we return DEBUG_MAX_FUNC_COUNT if we
  112. // fail to find a suitable match.
  113. //
  114. //-----------------------------------------------------------------------------
  115. DWORD
  116. __Find(
  117. VOID *pFuncAddr, DWORD *pdwNearFail)
  118. {
  119. DWORD dwLower ,dwUpper ,dwNewProbe ;
  120. *pdwNearFail = 0; // default failure value
  121. if (g_dwFuncCov_Cnt > 0)
  122. {
  123. dwLower = 0;
  124. dwUpper = g_dwFuncCov_Cnt - 1; // dwUpper points to a valid element
  125. do
  126. {
  127. dwNewProbe = (dwUpper + dwLower) / 2;
  128. //DISPDBG((0,"%x %d %d %d",pFuncAddr,dwLower,dwUpper,dwNewProbe));
  129. if (g_DbgFuncCoverage[dwNewProbe].pFuncAddr == pFuncAddr)
  130. {
  131. // Found!!!
  132. return dwNewProbe;
  133. }
  134. *pdwNearFail = dwNewProbe; // nearest element where we failed.
  135. // The new values for dwNewProbe make sure that we don't retest
  136. // the same value again unless dwUpper == dwLower in which case
  137. // we're done.
  138. if (g_DbgFuncCoverage[dwNewProbe].pFuncAddr > pFuncAddr)
  139. {
  140. if (dwNewProbe > 0)
  141. {
  142. dwUpper = dwNewProbe - 1;
  143. }
  144. else
  145. { // all elements in the array are larger than pFuncAdrr
  146. // so this is just a way to exit from the loop since
  147. // our vars are unsigned
  148. dwUpper = 0;
  149. dwLower = 1;
  150. }
  151. }
  152. else
  153. {
  154. dwLower = dwNewProbe + 1;
  155. }
  156. } while(dwUpper >= dwLower);
  157. }
  158. return DEBUG_MAX_FUNC_COUNT; // return error - element not found
  159. } // __Find
  160. //-----------------------------------------------------------------------------
  161. // __FindOrAdd
  162. //
  163. // Does a binary search on the g_DbgFuncCoverage array, but if the element
  164. // isn't there, it is added.
  165. //
  166. // If we fail to add the element, we return the DEBUG_MAX_FUNC_COUNT value
  167. //
  168. //-----------------------------------------------------------------------------
  169. DWORD
  170. __FindOrAdd(
  171. VOID *pFuncAddr,
  172. char *pszFuncName,
  173. DWORD dwLine ,
  174. char *pszFileName)
  175. {
  176. DWORD dwNearFail;
  177. DWORD iEntry;
  178. DWORD dwNewElem;
  179. BOOL bNeedToMoveElems;
  180. // Do the normal search of the element first
  181. iEntry = __Find(pFuncAddr, &dwNearFail);
  182. if (iEntry != DEBUG_MAX_FUNC_COUNT)
  183. {
  184. return iEntry; //we're done!
  185. }
  186. // Now we have to add the new element. Do we have enough space?
  187. if (g_dwFuncCov_Cnt == DEBUG_MAX_FUNC_COUNT)
  188. {
  189. g_dwFuncCov_Extra++; // Keep count of how many extra
  190. // entries we really need
  191. return DEBUG_MAX_FUNC_COUNT; // return error - not enough space left
  192. }
  193. // Do we need to move elements to insert the new one ?
  194. if ( g_dwFuncCov_Cnt == 0)
  195. {
  196. bNeedToMoveElems = FALSE;
  197. dwNewElem = 0;
  198. }
  199. else if ( (dwNearFail == g_dwFuncCov_Cnt - 1) &&
  200. (g_DbgFuncCoverage[dwNearFail].pFuncAddr < pFuncAddr) )
  201. {
  202. bNeedToMoveElems = FALSE;
  203. dwNewElem = g_dwFuncCov_Cnt;
  204. }
  205. else if (g_DbgFuncCoverage[dwNearFail].pFuncAddr < pFuncAddr)
  206. {
  207. bNeedToMoveElems = TRUE;
  208. dwNewElem = dwNearFail + 1;
  209. }
  210. else
  211. {
  212. bNeedToMoveElems = TRUE;
  213. dwNewElem = dwNearFail;
  214. }
  215. // Do the move inside the array if necessary
  216. if (bNeedToMoveElems)
  217. {
  218. // we need to move (g_dwFuncCov_Cnt - dwNewElem) elements
  219. // we use memmove as memcpy doesn't handle overlaps!
  220. // (remember: first param of memcpy is dst, 2nd is src!)
  221. memmove(&g_DbgFuncCoverage[dwNewElem+1],
  222. &g_DbgFuncCoverage[dwNewElem],
  223. sizeof(g_DbgFuncCoverage[0])*(g_dwFuncCov_Cnt - dwNewElem));
  224. // now cleanup the fields
  225. memset(&g_DbgFuncCoverage[dwNewElem],
  226. 0,
  227. sizeof(g_DbgFuncCoverage[dwNewElem]));
  228. }
  229. // Now init the main fields
  230. g_DbgFuncCoverage[dwNewElem].pFuncAddr = pFuncAddr;
  231. g_DbgFuncCoverage[dwNewElem].pszFuncName = pszFuncName;
  232. g_DbgFuncCoverage[dwNewElem].pszFileName = __ShortFileName(pszFileName);
  233. g_DbgFuncCoverage[dwNewElem].dwLine = dwLine;
  234. // Mark the fact that the array has grown by one element
  235. g_dwFuncCov_Cnt++;
  236. DISPDBG((DBGLVL,"*** DEBUG FUNC COVERAGE New Elem (total now:%d) %x @ %d",
  237. g_dwFuncCov_Cnt, pFuncAddr, dwNewElem));
  238. return dwNewElem;
  239. } // __FindOrAdd
  240. //-----------------------------------------------------------------------------
  241. // __GetTime
  242. //-----------------------------------------------------------------------------
  243. VOID
  244. __GetTime( LONGLONG *pllTime)
  245. {
  246. *pllTime = 0; //azn - temporary
  247. } // __GetTime
  248. //-----------------------------------------------------------------------------
  249. // Debug_Func_Entry
  250. //-----------------------------------------------------------------------------
  251. VOID
  252. Debug_Func_Entry(
  253. VOID *pFuncAddr,
  254. char *pszFuncName,
  255. DWORD dwLine ,
  256. char *pszFileName)
  257. {
  258. DWORD iEntry;
  259. LONGLONG llTimer;
  260. // Look for a log element for entry to this function. If not found it
  261. // is added to the current list of covered functions.
  262. iEntry = __FindOrAdd(pFuncAddr, pszFuncName, dwLine, pszFileName);
  263. // Didn't found one and no more space left in the internal data
  264. // structures ? Report error and return!
  265. if (iEntry == DEBUG_MAX_FUNC_COUNT)
  266. {
  267. DISPDBG((ERRLVL,"*** DEBUG FUNC COVERAGE ERROR in Debug_Func_Entry"));
  268. return;
  269. }
  270. // Update/Add information for this entry
  271. if (g_DbgFuncCoverage[iEntry].dwEntryCount != 0)
  272. {
  273. // This is an update
  274. g_DbgFuncCoverage[iEntry].dwEntryCount++;
  275. __GetTime(&llTimer);
  276. g_DbgFuncCoverage[iEntry].LastStartTime = llTimer;
  277. }
  278. else
  279. {
  280. // This is an addition
  281. g_DbgFuncCoverage[iEntry].dwEntryCount = 1;
  282. g_DbgFuncCoverage[iEntry].dwExitCount = 0;
  283. g_DbgFuncCoverage[iEntry].dwIndxLastRetVal = 0;
  284. __GetTime(&llTimer);
  285. g_DbgFuncCoverage[iEntry].LastStartTime = llTimer;
  286. g_DbgFuncCoverage[iEntry].MinTime = 0;
  287. g_DbgFuncCoverage[iEntry].MaxTime = 0;
  288. g_DbgFuncCoverage[iEntry].AvgTime = 0;
  289. }
  290. } // Debug_Func_Entry
  291. //-----------------------------------------------------------------------------
  292. // Debug_Func_Exit
  293. //-----------------------------------------------------------------------------
  294. VOID
  295. Debug_Func_Exit(
  296. VOID *pFuncAddr,
  297. DWORD dwRetVal,
  298. DWORD dwLine)
  299. {
  300. DWORD iEntry;
  301. LONGLONG llTimer;
  302. DWORD dwElapsedTime;
  303. DWORD dwDummy;
  304. DWORD iRVEntry;
  305. __GetTime(&llTimer);
  306. // Look for a log element for entry to this function
  307. iEntry = __Find(pFuncAddr, &dwDummy);
  308. // Record and update relevant info in g_DbgFuncCoverage
  309. if (iEntry != DEBUG_MAX_FUNC_COUNT)
  310. {
  311. // keep track of times we've exited this function
  312. g_DbgFuncCoverage[iEntry].dwExitCount++;
  313. // Keep track of elapsed times for this function
  314. //@@BEGIN_DDKSPLIT
  315. // possibly an evil data conversion - azn
  316. //@@END_DDKSPLIT
  317. dwElapsedTime = (DWORD)(llTimer -
  318. g_DbgFuncCoverage[iEntry].LastStartTime);
  319. if (dwElapsedTime > g_DbgFuncCoverage[iEntry].MaxTime)
  320. {
  321. g_DbgFuncCoverage[iEntry].MaxTime = dwElapsedTime;
  322. }
  323. if (dwElapsedTime < g_DbgFuncCoverage[iEntry].MinTime)
  324. {
  325. g_DbgFuncCoverage[iEntry].MinTime = dwElapsedTime;
  326. }
  327. g_DbgFuncCoverage[iEntry].AvgTime =
  328. ( (g_DbgFuncCoverage[iEntry].dwExitCount - 1)*
  329. g_DbgFuncCoverage[iEntry].AvgTime +
  330. dwElapsedTime
  331. ) / g_DbgFuncCoverage[iEntry].dwExitCount;
  332. g_DbgFuncCoverage[iEntry].LastStartTime = 0;
  333. }
  334. else
  335. {
  336. DISPDBG((ERRLVL,"*** DEBUG FUNC COVERAGE ERROR not found %x",pFuncAddr));
  337. return; // don't even try adding this to the return value table
  338. }
  339. iRVEntry = g_DbgFuncCoverage[iEntry].dwIndxLastRetVal;
  340. if (iRVEntry != 0)
  341. {
  342. // Check if the last time we recorded a return value for this function
  343. // it was the exact same one. This way will save space recording some
  344. // duplicate info. The method is not perfect, but it's fast.
  345. if (( g_DbgFuncRetVal[iRVEntry].pFuncAddr == pFuncAddr) &&
  346. ( g_DbgFuncRetVal[iRVEntry].dwRetVal == dwRetVal ) &&
  347. ( g_DbgFuncRetVal[iRVEntry].dwLine == dwLine ) )
  348. {
  349. //increment count for this event
  350. g_DbgFuncRetVal[iRVEntry].dwCount += 1;
  351. return; // we won't store a new record for this event
  352. }
  353. }
  354. // We couldn't save space, so we add info about the return value
  355. if (g_dwRetVal_Cnt < DEBUG_MAX_RETVALS)
  356. {
  357. g_DbgFuncCoverage[iEntry].dwIndxLastRetVal = g_dwRetVal_Cnt;
  358. g_DbgFuncRetVal[g_dwRetVal_Cnt].pFuncAddr = pFuncAddr;
  359. g_DbgFuncRetVal[g_dwRetVal_Cnt].dwRetVal = dwRetVal;
  360. g_DbgFuncRetVal[g_dwRetVal_Cnt].dwLine = dwLine;
  361. g_DbgFuncRetVal[g_dwRetVal_Cnt].dwCount = 1;
  362. g_dwRetVal_Cnt++;
  363. }
  364. } // Debug_Func_Exit
  365. //-----------------------------------------------------------------------------
  366. //
  367. // Debug_Func_Report_And_Reset
  368. //
  369. // Report the accumulated stats and then reset them.
  370. //
  371. // This should be called through the DrvEscape mechanism(Win2K) or through some
  372. // easily controllable code path which we can use to trigger it.
  373. //
  374. //-----------------------------------------------------------------------------
  375. VOID
  376. Debug_Func_Report_And_Reset(void)
  377. {
  378. DWORD i,j,k; // counters
  379. DWORD dwCount;
  380. DISPDBG((ERRLVL,"********* DEBUG FUNC COVERAGE (Debug_Func_Report) *********"));
  381. // Report if we have overflowed in any of our internal structures
  382. // which would invalidate much of our results.
  383. if (g_dwFuncCov_Cnt >= DEBUG_MAX_FUNC_COUNT)
  384. {
  385. DISPDBG((ERRLVL,"*** DEBUG FUNC COVERAGE: g_DbgFuncCoverage exceeded "
  386. "%d entries by %d ***",
  387. DEBUG_MAX_FUNC_COUNT,
  388. g_dwFuncCov_Extra));
  389. }
  390. if (g_dwRetVal_Cnt >= DEBUG_MAX_RETVALS)
  391. {
  392. DISPDBG((ERRLVL,"*** DEBUG FUNC COVERAGE: g_DbgFuncRetVal exceeded "
  393. "%d entries ***",DEBUG_MAX_RETVALS));
  394. }
  395. // Headers of function coverage report
  396. DISPDBG((ERRLVL,"%25s %12s %4s %6s %6s %8s",
  397. "Function","File","Line","#Entry","#Exit","ExitValue"));
  398. // Go through each function called and report on its results
  399. for (i = 0; i < g_dwFuncCov_Cnt; i++)
  400. {
  401. DISPDBG((ERRLVL,"%25s %12s %4d %6d %6d",
  402. g_DbgFuncCoverage[i].pszFuncName,
  403. g_DbgFuncCoverage[i].pszFileName,
  404. g_DbgFuncCoverage[i].dwLine,
  405. g_DbgFuncCoverage[i].dwEntryCount,
  406. g_DbgFuncCoverage[i].dwExitCount));
  407. // Get result values
  408. for(j = 0; j < g_dwRetVal_Cnt; j++)
  409. {
  410. if(g_DbgFuncRetVal[j].pFuncAddr ==
  411. g_DbgFuncCoverage[i].pFuncAddr)
  412. {
  413. // This entry is a valid exit value report for
  414. // our g_DbgFuncCoverage entry, count instances
  415. dwCount = g_DbgFuncRetVal[j].dwCount;
  416. // Now get rid of any duplicate records of this
  417. // same exit event while counting
  418. for (k = j + 1; k < g_dwRetVal_Cnt; k++)
  419. {
  420. if ( (g_DbgFuncRetVal[j].pFuncAddr ==
  421. g_DbgFuncRetVal[k].pFuncAddr) &&
  422. (g_DbgFuncRetVal[j].dwLine ==
  423. g_DbgFuncRetVal[k].dwLine) &&
  424. (g_DbgFuncRetVal[j].dwRetVal ==
  425. g_DbgFuncRetVal[k].dwRetVal))
  426. {
  427. dwCount += g_DbgFuncRetVal[k].dwCount;
  428. g_DbgFuncRetVal[k].pFuncAddr = NULL;
  429. g_DbgFuncRetVal[k].dwRetVal = 0;
  430. g_DbgFuncRetVal[k].dwLine = 0;
  431. g_DbgFuncRetVal[k].dwCount = 0;
  432. }
  433. }
  434. // Display it
  435. DISPDBG((ERRLVL,"%25s %12s %4d %6d %6s %8d",
  436. "\"",
  437. g_DbgFuncCoverage[i].pszFileName,
  438. g_DbgFuncRetVal[j].dwLine,
  439. dwCount,"",
  440. g_DbgFuncRetVal[j].dwRetVal));
  441. }
  442. }
  443. }
  444. DISPDBG((ERRLVL,
  445. "************************************************************"));
  446. // Clear structures for next round of statistics gathering
  447. for (i = 0; i < DEBUG_MAX_RETVALS; i++)
  448. {
  449. g_DbgFuncRetVal[i].pFuncAddr = NULL;
  450. g_DbgFuncRetVal[i].dwRetVal = 0;
  451. g_DbgFuncRetVal[i].dwLine = 0;
  452. g_DbgFuncRetVal[i].dwCount = 0;
  453. }
  454. for (i= 0; i < DEBUG_MAX_FUNC_COUNT; i++)
  455. {
  456. g_DbgFuncCoverage[i].pFuncAddr = NULL;
  457. g_DbgFuncCoverage[i].pszFuncName = NULL;
  458. g_DbgFuncCoverage[i].pszFileName = NULL;
  459. g_DbgFuncCoverage[i].dwLine = 0;
  460. g_DbgFuncCoverage[i].dwEntryCount = 0;
  461. g_DbgFuncCoverage[i].dwExitCount = 0;
  462. g_DbgFuncCoverage[i].dwIndxLastRetVal = 0;
  463. g_DbgFuncCoverage[i].LastStartTime = 0;
  464. g_DbgFuncCoverage[i].MinTime = 0;
  465. g_DbgFuncCoverage[i].MaxTime = 0;
  466. g_DbgFuncCoverage[i].AvgTime = 0;
  467. }
  468. g_dwRetVal_Cnt = 0;
  469. g_dwFuncCov_Cnt = 0;
  470. g_dwFuncCov_Extra = 0;
  471. } // Debug_Func_Report
  472. #endif // DBG_TRACK_FUNCS
  473. #if DBG_TRACK_CODE
  474. //-----------------------------------------------------------------------------
  475. //
  476. // ******************** STATEMENT COVERAGE DEBUGGING SUPPORT ******************
  477. //
  478. //-----------------------------------------------------------------------------
  479. // Maximum of code branches to be tracked. Code will take care of not exceeding
  480. // this, but it should be adjusted upward if necessary.
  481. #define DEBUG_MAX_CODE_COUNT 20000
  482. struct {
  483. VOID *pCodeAddr; //
  484. char *pszFileName; //
  485. DWORD dwLine; //
  486. DWORD dwCodeType; //
  487. DWORD dwCountFALSE; //
  488. DWORD dwCountTRUE; //
  489. } g_DbgCodeCoverage[DEBUG_MAX_CODE_COUNT];
  490. DWORD g_dwCodeCov_Cnt = 0;
  491. static char* g_cDbgCodeStrings[DBG_FOR_CODE+1] = { "NONE",
  492. "IF" ,
  493. "WHILE",
  494. "SWITCH",
  495. "FOR" };
  496. //-----------------------------------------------------------------------------
  497. // __FindCode
  498. //
  499. // Does a binary search on the g_DbgCodeCoverage array
  500. //
  501. // Since 0 is a valid array element, we return DEBUG_MAX_CODE_COUNT if we
  502. // fail to find a suitable match.
  503. //
  504. //-----------------------------------------------------------------------------
  505. DWORD
  506. __FindCode(
  507. VOID *pCodeAddr,
  508. DWORD *pdwNearFail)
  509. {
  510. DWORD dwLower ,dwUpper ,dwNewProbe ;
  511. *pdwNearFail = 0; // default failure value
  512. if (g_dwCodeCov_Cnt > 0)
  513. {
  514. dwLower = 0;
  515. dwUpper = g_dwCodeCov_Cnt - 1; // dwUpper points to a valid element
  516. do
  517. {
  518. dwNewProbe = (dwUpper + dwLower) / 2;
  519. if (g_DbgCodeCoverage[dwNewProbe].pCodeAddr == pCodeAddr)
  520. {
  521. // Found!!!
  522. return dwNewProbe;
  523. }
  524. *pdwNearFail = dwNewProbe; // nearest element where we failed.
  525. // The new values for dwNewProbe make sure that we don't retest
  526. // the same value again unless dwUpper == dwLower in which case
  527. // we're done.
  528. if (g_DbgCodeCoverage[dwNewProbe].pCodeAddr > pCodeAddr)
  529. {
  530. if (dwNewProbe > 0)
  531. {
  532. dwUpper = dwNewProbe - 1;
  533. }
  534. else
  535. { // all elements in the array are larger than pCodeAdrr
  536. // so this is just a way to exit from the loop since
  537. // our vars are unsigned
  538. dwUpper = 0;
  539. dwLower = 1;
  540. }
  541. }
  542. else
  543. {
  544. dwLower = dwNewProbe + 1;
  545. }
  546. } while(dwUpper >= dwLower);
  547. }
  548. return DEBUG_MAX_CODE_COUNT; // return error - element not found
  549. } // __FindCode
  550. //-----------------------------------------------------------------------------
  551. // __FindOrAddCode
  552. //
  553. // Does a binary search on the g_DbgCodeCoverage array, but if the element
  554. // isn't there, it is added.
  555. //
  556. // If we fail to add the element, we return the DEBUG_MAX_CODE_COUNT value
  557. //
  558. //-----------------------------------------------------------------------------
  559. DWORD
  560. __FindOrAddCode(
  561. VOID *pCodeAddr,
  562. DWORD dwLine ,
  563. char *pszFileName)
  564. {
  565. DWORD dwNearFail;
  566. DWORD iEntry;
  567. DWORD dwNewElem;
  568. BOOL bNeedToMoveElems;
  569. // Do the normal search of the element first
  570. iEntry = __FindCode(pCodeAddr, &dwNearFail);
  571. if (iEntry != DEBUG_MAX_CODE_COUNT)
  572. {
  573. return iEntry; //we're done!
  574. }
  575. // Now we have to add the new element. Do we have enough space?
  576. if (g_dwCodeCov_Cnt == DEBUG_MAX_CODE_COUNT)
  577. {
  578. return DEBUG_MAX_CODE_COUNT; // return error - not enough space left
  579. }
  580. // Do we need to move elements to insert the new one ?
  581. if ( g_dwCodeCov_Cnt == 0)
  582. {
  583. bNeedToMoveElems = FALSE;
  584. dwNewElem = 0;
  585. }
  586. else if ( (dwNearFail == g_dwCodeCov_Cnt - 1) &&
  587. (g_DbgCodeCoverage[dwNearFail].pCodeAddr < pCodeAddr) )
  588. {
  589. bNeedToMoveElems = FALSE;
  590. dwNewElem = g_dwCodeCov_Cnt;
  591. }
  592. else if (g_DbgCodeCoverage[dwNearFail].pCodeAddr < pCodeAddr)
  593. {
  594. bNeedToMoveElems = TRUE;
  595. dwNewElem = dwNearFail + 1;
  596. }
  597. else
  598. {
  599. bNeedToMoveElems = TRUE;
  600. dwNewElem = dwNearFail;
  601. }
  602. // Do the move inside the array if necessary
  603. if (bNeedToMoveElems)
  604. {
  605. // we need to move (g_dwFuncCov_Cnt - dwNewElem) elements
  606. // we use memmove as memcpy doesn't handle overlaps!
  607. // (remember: first param of memcpy is dst, 2nd is src!)
  608. memmove(&g_DbgCodeCoverage[dwNewElem+1],
  609. &g_DbgCodeCoverage[dwNewElem],
  610. sizeof(g_DbgCodeCoverage[0])*(g_dwCodeCov_Cnt - dwNewElem));
  611. // now cleanup the fields
  612. memset(&g_DbgCodeCoverage[dwNewElem],
  613. 0,
  614. sizeof(g_DbgCodeCoverage[dwNewElem]));
  615. }
  616. // Now init the main fields
  617. g_DbgCodeCoverage[dwNewElem].pCodeAddr = pCodeAddr;
  618. g_DbgCodeCoverage[dwNewElem].pszFileName = __ShortFileName(pszFileName);
  619. g_DbgCodeCoverage[dwNewElem].dwLine = dwLine;
  620. g_DbgCodeCoverage[dwNewElem].dwCodeType = 0;
  621. g_DbgCodeCoverage[dwNewElem].dwCountFALSE = 0;
  622. g_DbgCodeCoverage[dwNewElem].dwCountTRUE = 0;
  623. // Mark the fact that the array has grown by one element
  624. g_dwCodeCov_Cnt++;
  625. // Check if we're about to fail! (in order to report this only once)
  626. if (g_dwCodeCov_Cnt == DEBUG_MAX_CODE_COUNT)
  627. {
  628. DISPDBG((ERRLVL,"*** DEBUG CODE COVERAGE ERROR in Debug_Code_Coverage"));
  629. }
  630. return dwNewElem;
  631. } // __FindOrAddCode
  632. //-----------------------------------------------------------------------------
  633. // Debug_Code_Coverage
  634. //-----------------------------------------------------------------------------
  635. BOOL
  636. Debug_Code_Coverage(
  637. DWORD dwCodeType,
  638. DWORD dwLine ,
  639. char *pszFileName,
  640. BOOL bCodeResult)
  641. {
  642. DWORD iEntry;
  643. DWORD *pCodeAddr;
  644. // Get the 32-bit address of our caller from the stack
  645. __asm mov eax, [ebp+0x4];
  646. __asm mov pCodeAddr,eax;
  647. // Look for a log element for entry to this code. If not found it
  648. // is added to the current list of covered code.
  649. iEntry = __FindOrAddCode(pCodeAddr, dwLine, pszFileName);
  650. // Didn't found one and no more space left in the internal data
  651. // structures ? Get out and do nothing!
  652. if (iEntry == DEBUG_MAX_CODE_COUNT)
  653. {
  654. return bCodeResult;
  655. }
  656. if (dwCodeType == DBG_IF_CODE || dwCodeType == DBG_WHILE_CODE )
  657. {
  658. // Update/Add information for this entry
  659. g_DbgCodeCoverage[iEntry].dwCodeType = dwCodeType;
  660. if (bCodeResult)
  661. {
  662. g_DbgCodeCoverage[iEntry].dwCountTRUE++;
  663. }
  664. else
  665. {
  666. g_DbgCodeCoverage[iEntry].dwCountFALSE++;
  667. }
  668. }
  669. else if (dwCodeType == DBG_SWITCH_CODE)
  670. {
  671. // special case for the switch statement since its multivalued
  672. // Is the entry new? (uninitalized)
  673. if(g_DbgCodeCoverage[iEntry].dwCodeType == 0)
  674. {
  675. // just init and get out of here
  676. g_DbgCodeCoverage[iEntry].dwCodeType = DBG_SWITCH_CODE;
  677. g_DbgCodeCoverage[iEntry].dwCountFALSE = bCodeResult; // switch value
  678. g_DbgCodeCoverage[iEntry].dwCountTRUE = 1; // found once
  679. }
  680. else
  681. {
  682. // need to look for already initialized elememt
  683. int iLookAt;
  684. // look at current element and back
  685. DWORD dwNewElem;
  686. iLookAt = iEntry;
  687. while ( (iLookAt >= 0 ) &&
  688. (g_DbgCodeCoverage[iLookAt].pCodeAddr == pCodeAddr) )
  689. {
  690. if (g_DbgCodeCoverage[iLookAt].dwCountFALSE == (DWORD)bCodeResult)
  691. {
  692. // found - so update and get out of here
  693. g_DbgCodeCoverage[iLookAt].dwCountTRUE++;
  694. return bCodeResult;
  695. }
  696. // move to previous
  697. iLookAt--;
  698. }
  699. // look forward from current element
  700. iLookAt = iEntry + 1;
  701. while ( ((DWORD)iLookAt < g_dwCodeCov_Cnt ) &&
  702. (g_DbgCodeCoverage[iLookAt].pCodeAddr == pCodeAddr) )
  703. {
  704. if (g_DbgCodeCoverage[iLookAt].dwCountFALSE == (DWORD)bCodeResult)
  705. {
  706. // found - so update and get out of here
  707. g_DbgCodeCoverage[iLookAt].dwCountTRUE++;
  708. return bCodeResult;
  709. }
  710. // move to next
  711. iLookAt++;
  712. }
  713. // not found - so we must add it!
  714. dwNewElem = iEntry;
  715. // we need to move (g_dwFuncCov_Cnt - dwNewElem) elements
  716. // we use memmove as memcpy doesn't handle overlaps!
  717. // (remember: first param of memcpy is dst, 2nd is src!)
  718. memmove(&g_DbgCodeCoverage[dwNewElem+1],
  719. &g_DbgCodeCoverage[dwNewElem],
  720. sizeof(g_DbgCodeCoverage[0])*(g_dwCodeCov_Cnt - dwNewElem));
  721. // now cleanup the fields
  722. memset(&g_DbgCodeCoverage[dwNewElem],
  723. 0,
  724. sizeof(g_DbgCodeCoverage[dwNewElem]));
  725. // now init them
  726. g_DbgCodeCoverage[dwNewElem].pCodeAddr = pCodeAddr;
  727. g_DbgCodeCoverage[dwNewElem].pszFileName =
  728. g_DbgCodeCoverage[dwNewElem+1].pszFileName;
  729. g_DbgCodeCoverage[dwNewElem].dwLine = dwLine;
  730. g_DbgCodeCoverage[dwNewElem].dwCodeType = DBG_SWITCH_CODE;
  731. g_DbgCodeCoverage[dwNewElem].dwCountFALSE = bCodeResult; // switch value
  732. g_DbgCodeCoverage[dwNewElem].dwCountTRUE = 1; // found once
  733. }
  734. }
  735. return bCodeResult;
  736. } // Debug_Code_Coverage
  737. //-----------------------------------------------------------------------------
  738. //
  739. // Debug_Code_Report_And_Reset
  740. //
  741. // Report the accumulated stats and then reset them.
  742. //
  743. // This should be called through the DrvEscape mechanism(Win2K) or through some
  744. // easily controllable code path which we can use to trigger it.
  745. //
  746. //-----------------------------------------------------------------------------
  747. VOID
  748. Debug_Code_Report_And_Reset(void)
  749. {
  750. DWORD i; // counters
  751. DISPDBG((ERRLVL,
  752. "********* DEBUG FUNC COVERAGE (Debug_Code_Report) *********"));
  753. // Report if we have overflowed in any of our internal structures
  754. // which would invalidate much of our results.
  755. if (g_dwCodeCov_Cnt >= DEBUG_MAX_CODE_COUNT)
  756. {
  757. DISPDBG((ERRLVL,"*** DEBUG CODE COVERAGE: g_DbgCodeCoverage exceeded "
  758. "%d entries ***",DEBUG_MAX_CODE_COUNT));
  759. }
  760. // Headers of code coverage report
  761. DISPDBG((ERRLVL,"%12s %4s %8s %6s %6s",
  762. "File","Line","Code","FALSE","TRUE"));
  763. // Go through each code called and report on its results
  764. for (i = 0; i < g_dwCodeCov_Cnt; i++)
  765. {
  766. #if DBG_TRACK_CODE_REPORT_PROBLEMS_ONLY
  767. // Report only
  768. // - if's that branched only one way
  769. // - while's which were evaluated but not entered
  770. if ( ( (g_DbgCodeCoverage[i].dwCodeType == DBG_IF_CODE) &&
  771. (g_DbgCodeCoverage[i].dwCountFALSE == 0 ||
  772. g_DbgCodeCoverage[i].dwCountTRUE == 0) ) ||
  773. ( (g_DbgCodeCoverage[i].dwCodeType == DBG_WHILE_CODE) &&
  774. (g_DbgCodeCoverage[i].dwCountTRUE == 0) ) ||
  775. ( (g_DbgCodeCoverage[i].dwCodeType == DBG_SWITCH_CODE)) )
  776. #endif
  777. // We report all the conditionals we've gone through so far
  778. DISPDBG((ERRLVL,"%12s %4d %8s %6d %6d",
  779. g_DbgCodeCoverage[i].pszFileName,
  780. g_DbgCodeCoverage[i].dwLine,
  781. g_cDbgCodeStrings[g_DbgCodeCoverage[i].dwCodeType],
  782. g_DbgCodeCoverage[i].dwCountFALSE,
  783. g_DbgCodeCoverage[i].dwCountTRUE ));
  784. }
  785. DISPDBG((ERRLVL,
  786. "************************************************************"));
  787. // Clear structures for next round of statistics gathering
  788. for (i= 0; i < DEBUG_MAX_CODE_COUNT; i++)
  789. {
  790. g_DbgCodeCoverage[i].pCodeAddr = NULL;
  791. g_DbgCodeCoverage[i].pszFileName = NULL;
  792. g_DbgCodeCoverage[i].dwLine = 0;
  793. g_DbgCodeCoverage[i].dwCodeType = 0;
  794. g_DbgCodeCoverage[i].dwCountFALSE = 0;
  795. g_DbgCodeCoverage[i].dwCountTRUE = 0;
  796. }
  797. g_dwCodeCov_Cnt = 0;
  798. } // Debug_Code_Report_And_Reset
  799. #endif // DBG_TRACK_CODE
  800. //-----------------------------------------------------------------------------
  801. //
  802. // ******************** PUBLIC DATA STRUCTURE DUMPING ************************
  803. //
  804. //-----------------------------------------------------------------------------
  805. //
  806. // These are functions that help to dump the values of common DDI structures
  807. //
  808. //-----------------------------------------------------------------------------
  809. //-----------------------------------------------------------------------------
  810. //
  811. // DumpD3DBlend
  812. //
  813. // Dumps a D3DBLEND value
  814. //
  815. //-----------------------------------------------------------------------------
  816. void DumpD3DBlend(int Level, DWORD i )
  817. {
  818. switch ((D3DBLEND)i)
  819. {
  820. case D3DBLEND_ZERO:
  821. DISPDBG((Level, " ZERO"));
  822. break;
  823. case D3DBLEND_ONE:
  824. DISPDBG((Level, " ONE"));
  825. break;
  826. case D3DBLEND_SRCCOLOR:
  827. DISPDBG((Level, " SRCCOLOR"));
  828. break;
  829. case D3DBLEND_INVSRCCOLOR:
  830. DISPDBG((Level, " INVSRCCOLOR"));
  831. break;
  832. case D3DBLEND_SRCALPHA:
  833. DISPDBG((Level, " SRCALPHA"));
  834. break;
  835. case D3DBLEND_INVSRCALPHA:
  836. DISPDBG((Level, " INVSRCALPHA"));
  837. break;
  838. case D3DBLEND_DESTALPHA:
  839. DISPDBG((Level, " DESTALPHA"));
  840. break;
  841. case D3DBLEND_INVDESTALPHA:
  842. DISPDBG((Level, " INVDESTALPHA"));
  843. break;
  844. case D3DBLEND_DESTCOLOR:
  845. DISPDBG((Level, " DESTCOLOR"));
  846. break;
  847. case D3DBLEND_INVDESTCOLOR:
  848. DISPDBG((Level, " INVDESTCOLOR"));
  849. break;
  850. case D3DBLEND_SRCALPHASAT:
  851. DISPDBG((Level, " SRCALPHASAT"));
  852. break;
  853. case D3DBLEND_BOTHSRCALPHA:
  854. DISPDBG((Level, " BOTHSRCALPHA"));
  855. break;
  856. case D3DBLEND_BOTHINVSRCALPHA:
  857. DISPDBG((Level, " BOTHINVSRCALPHA"));
  858. break;
  859. }
  860. } // DumpD3DBlend
  861. //-----------------------------------------------------------------------------
  862. //
  863. // DumpD3DLight
  864. //
  865. // Dumps a D3DLIGHT7 structure
  866. //
  867. //-----------------------------------------------------------------------------
  868. void DumpD3DLight(int DebugLevel, D3DLIGHT7* pLight)
  869. {
  870. // FIXME
  871. DISPDBG((DebugLevel, "dltType: %d", pLight->dltType));
  872. DISPDBG((DebugLevel, "dcvDiffuse: (%f,%f,%f)",
  873. pLight->dcvDiffuse.r,
  874. pLight->dcvDiffuse.g,
  875. pLight->dcvDiffuse.b,
  876. pLight->dcvDiffuse.a));
  877. DISPDBG((DebugLevel, "dvPosition: (%f,%f,%f)",
  878. pLight->dvPosition.x,
  879. pLight->dvPosition.y,
  880. pLight->dvPosition.z));
  881. DISPDBG((DebugLevel, "dvDirection: (%f,%f,%f)",
  882. pLight->dvDirection.x,
  883. pLight->dvDirection.y,
  884. pLight->dvDirection.z));
  885. DISPDBG((DebugLevel, "dvRange: %f", pLight->dvRange));
  886. DISPDBG((DebugLevel, "dvFalloff: %f", pLight->dvFalloff));
  887. DISPDBG((DebugLevel, "dvAttenuation0: %f", pLight->dvAttenuation0));
  888. DISPDBG((DebugLevel, "dvAttenuation1: %f", pLight->dvAttenuation1));
  889. DISPDBG((DebugLevel, "dvAttenuation2: %f", pLight->dvAttenuation2));
  890. DISPDBG((DebugLevel, "dvTheta: %f", pLight->dvTheta));
  891. DISPDBG((DebugLevel, "dvPhi: %f", pLight->dvPhi));
  892. } // DumpD3DLight
  893. //-----------------------------------------------------------------------------
  894. //
  895. // DumpD3DMaterial
  896. //
  897. // Dumps a D3DMATERIAL7 structure
  898. //
  899. //-----------------------------------------------------------------------------
  900. void DumpD3DMaterial(int DebugLevel, D3DMATERIAL7* pMaterial)
  901. {
  902. DISPDBG((DebugLevel, "Diffuse (%f, %f, %f)",
  903. pMaterial->diffuse.r,
  904. pMaterial->diffuse.g,
  905. pMaterial->diffuse.b,
  906. pMaterial->diffuse.a));
  907. DISPDBG((DebugLevel, "Ambient (%f, %f, %f)",
  908. pMaterial->ambient.r,
  909. pMaterial->ambient.g,
  910. pMaterial->ambient.b,
  911. pMaterial->ambient.a));
  912. DISPDBG((DebugLevel, "Specular (%f, %f, %f)",
  913. pMaterial->specular.r,
  914. pMaterial->specular.g,
  915. pMaterial->specular.b,
  916. pMaterial->specular.a));
  917. DISPDBG((DebugLevel, "Emmisive (%f, %f, %f)",
  918. pMaterial->emissive.r,
  919. pMaterial->emissive.g,
  920. pMaterial->emissive.b,
  921. pMaterial->emissive.a));
  922. DISPDBG((DebugLevel, "Power (%f)", pMaterial->power));
  923. } // DumpD3DMaterial
  924. //-----------------------------------------------------------------------------
  925. //
  926. // DumpD3DMatrix
  927. //
  928. // Dumps a D3DMATRIX structure
  929. //
  930. //-----------------------------------------------------------------------------
  931. void DumpD3DMatrix(int DebugLevel, D3DMATRIX* pMatrix)
  932. {
  933. DISPDBG((DebugLevel, "(%f) (%f) (%f) (%f)",
  934. pMatrix->_11,
  935. pMatrix->_12,
  936. pMatrix->_13,
  937. pMatrix->_14));
  938. DISPDBG((DebugLevel, "(%f) (%f) (%f) (%f)",
  939. pMatrix->_21,
  940. pMatrix->_22,
  941. pMatrix->_23,
  942. pMatrix->_24));
  943. DISPDBG((DebugLevel, "(%f) (%f) (%f) (%f)",
  944. pMatrix->_31,
  945. pMatrix->_32,
  946. pMatrix->_33,
  947. pMatrix->_34));
  948. DISPDBG((DebugLevel, "(%f) (%f) (%f) (%f)",
  949. pMatrix->_41,
  950. pMatrix->_42,
  951. pMatrix->_43,
  952. pMatrix->_44));
  953. } // DumpD3DMatrix
  954. //-----------------------------------------------------------------------------
  955. //
  956. // DumpD3DState
  957. //
  958. // Dumps relevant D3D RS and TSS
  959. //
  960. //-----------------------------------------------------------------------------
  961. void DumpD3DState(int lvl, DWORD RS[], TexStageState TS[])
  962. {
  963. #define DUMPRS(rs) DISPDBG((lvl,"%s = 0x%08x",#rs,RS[rs]));
  964. DWORD i,j;
  965. DISPDBG((lvl,"RELEVANT DX7 renderstates:"));
  966. DUMPRS( D3DRENDERSTATE_ZENABLE );
  967. DUMPRS( D3DRENDERSTATE_FILLMODE );
  968. DUMPRS( D3DRENDERSTATE_SHADEMODE );
  969. DUMPRS( D3DRENDERSTATE_LINEPATTERN );
  970. DUMPRS( D3DRENDERSTATE_ZWRITEENABLE );
  971. DUMPRS( D3DRENDERSTATE_ALPHATESTENABLE );
  972. DUMPRS( D3DRENDERSTATE_LASTPIXEL );
  973. DUMPRS( D3DRENDERSTATE_SRCBLEND );
  974. DUMPRS( D3DRENDERSTATE_DESTBLEND );
  975. DUMPRS( D3DRENDERSTATE_CULLMODE );
  976. DUMPRS( D3DRENDERSTATE_ZFUNC );
  977. DUMPRS( D3DRENDERSTATE_ALPHAREF );
  978. DUMPRS( D3DRENDERSTATE_ALPHAFUNC );
  979. DUMPRS( D3DRENDERSTATE_DITHERENABLE );
  980. DUMPRS( D3DRENDERSTATE_BLENDENABLE );
  981. DUMPRS( D3DRENDERSTATE_FOGENABLE );
  982. DUMPRS( D3DRENDERSTATE_SPECULARENABLE );
  983. DUMPRS( D3DRENDERSTATE_ZVISIBLE );
  984. DUMPRS( D3DRENDERSTATE_STIPPLEDALPHA );
  985. DUMPRS( D3DRENDERSTATE_FOGCOLOR );
  986. DUMPRS( D3DRENDERSTATE_FOGTABLEMODE );
  987. DUMPRS( D3DRENDERSTATE_FOGTABLESTART );
  988. DUMPRS( D3DRENDERSTATE_FOGTABLEEND );
  989. DUMPRS( D3DRENDERSTATE_FOGTABLEDENSITY );
  990. DUMPRS( D3DRENDERSTATE_EDGEANTIALIAS );
  991. DUMPRS( D3DRENDERSTATE_ZBIAS );
  992. DUMPRS( D3DRENDERSTATE_RANGEFOGENABLE );
  993. DUMPRS( D3DRENDERSTATE_STENCILENABLE );
  994. DUMPRS( D3DRENDERSTATE_STENCILFAIL );
  995. DUMPRS( D3DRENDERSTATE_STENCILZFAIL );
  996. DUMPRS( D3DRENDERSTATE_STENCILPASS );
  997. DUMPRS( D3DRENDERSTATE_STENCILFUNC );
  998. DUMPRS( D3DRENDERSTATE_STENCILREF );
  999. DUMPRS( D3DRENDERSTATE_STENCILMASK );
  1000. DUMPRS( D3DRENDERSTATE_STENCILWRITEMASK );
  1001. DUMPRS( D3DRENDERSTATE_TEXTUREFACTOR );
  1002. DUMPRS( D3DRENDERSTATE_WRAP0 );
  1003. DUMPRS( D3DRENDERSTATE_WRAP1 );
  1004. DUMPRS( D3DRENDERSTATE_WRAP2 );
  1005. DUMPRS( D3DRENDERSTATE_WRAP3 );
  1006. DUMPRS( D3DRENDERSTATE_WRAP4 );
  1007. DUMPRS( D3DRENDERSTATE_WRAP5 );
  1008. DUMPRS( D3DRENDERSTATE_WRAP6 );
  1009. DUMPRS( D3DRENDERSTATE_WRAP7 );
  1010. DUMPRS( D3DRENDERSTATE_LOCALVIEWER );
  1011. DUMPRS( D3DRENDERSTATE_CLIPPING );
  1012. DUMPRS( D3DRENDERSTATE_LIGHTING );
  1013. DUMPRS( D3DRENDERSTATE_AMBIENT );
  1014. DUMPRS( D3DRENDERSTATE_SCENECAPTURE );
  1015. DUMPRS( D3DRENDERSTATE_EVICTMANAGEDTEXTURES );
  1016. DUMPRS( D3DRENDERSTATE_TEXTUREHANDLE );
  1017. DUMPRS( D3DRENDERSTATE_ANTIALIAS );
  1018. DUMPRS( D3DRENDERSTATE_TEXTUREPERSPECTIVE );
  1019. DUMPRS( D3DRENDERSTATE_TEXTUREMAPBLEND );
  1020. DUMPRS( D3DRENDERSTATE_TEXTUREMAG );
  1021. DUMPRS( D3DRENDERSTATE_TEXTUREMIN );
  1022. DUMPRS( D3DRENDERSTATE_WRAPU );
  1023. DUMPRS( D3DRENDERSTATE_WRAPV );
  1024. DUMPRS( D3DRENDERSTATE_TEXTUREADDRESS );
  1025. DUMPRS( D3DRENDERSTATE_TEXTUREADDRESSU );
  1026. DUMPRS( D3DRENDERSTATE_TEXTUREADDRESSV );
  1027. DUMPRS( D3DRENDERSTATE_MIPMAPLODBIAS );
  1028. DUMPRS( D3DRENDERSTATE_BORDERCOLOR );
  1029. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN00 );
  1030. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN01 );
  1031. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN02 );
  1032. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN03 );
  1033. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN04 );
  1034. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN05 );
  1035. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN06 );
  1036. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN07 );
  1037. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN08 );
  1038. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN09 );
  1039. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN10 );
  1040. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN11 );
  1041. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN12 );
  1042. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN13 );
  1043. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN14 );
  1044. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN15 );
  1045. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN16 );
  1046. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN17 );
  1047. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN18 );
  1048. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN19 );
  1049. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN20 );
  1050. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN21 );
  1051. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN22 );
  1052. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN23 );
  1053. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN24 );
  1054. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN25 );
  1055. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN26 );
  1056. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN27 );
  1057. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN28 );
  1058. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN29 );
  1059. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN30 );
  1060. DUMPRS( D3DRENDERSTATE_STIPPLEPATTERN31 );
  1061. DUMPRS( D3DRENDERSTATE_ROP2 );
  1062. DUMPRS( D3DRENDERSTATE_PLANEMASK );
  1063. DUMPRS( D3DRENDERSTATE_MONOENABLE );
  1064. DUMPRS( D3DRENDERSTATE_SUBPIXEL );
  1065. DUMPRS( D3DRENDERSTATE_SUBPIXELX );
  1066. DUMPRS( D3DRENDERSTATE_STIPPLEENABLE );
  1067. DUMPRS( D3DRENDERSTATE_COLORKEYENABLE );
  1068. #if DX8_DDI
  1069. DISPDBG((lvl,"RELEVANT DX8 renderstates:"));
  1070. DUMPRS( D3DRS_POINTSIZE );
  1071. DUMPRS( D3DRS_POINTSPRITEENABLE );
  1072. DUMPRS( D3DRS_POINTSIZE_MIN );
  1073. DUMPRS( D3DRS_POINTSIZE_MAX );
  1074. DUMPRS( D3DRS_POINTSCALEENABLE );
  1075. DUMPRS( D3DRS_POINTSCALE_A );
  1076. DUMPRS( D3DRS_POINTSCALE_B );
  1077. DUMPRS( D3DRS_POINTSCALE_C );
  1078. DUMPRS( D3DRS_SOFTWAREVERTEXPROCESSING );
  1079. DUMPRS( D3DRS_COLORWRITEENABLE );
  1080. DUMPRS( D3DRS_MULTISAMPLEANTIALIAS );
  1081. #endif // DX8_DDI
  1082. for (i=0; i<D3DHAL_TSS_MAXSTAGES; i++)
  1083. {
  1084. DISPDBG((lvl," TS[%d].",i));
  1085. for (j=0; j<D3DTSS_MAX; j++)
  1086. {
  1087. DISPDBG((lvl, " .[%d] = 0x%08x",j,TS[i].m_dwVal[j] ));
  1088. }
  1089. }
  1090. } // DumpD3DState
  1091. //-----------------------------------------------------------------------------
  1092. //
  1093. // DumpVertices
  1094. //
  1095. // Dumps vertices from a VB
  1096. //
  1097. //-----------------------------------------------------------------------------
  1098. void DumpVertices(int lvl,
  1099. P3_D3DCONTEXT* pContext,
  1100. LPBYTE lpVertices,
  1101. DWORD dwNumVertices)
  1102. {
  1103. DWORD i,j;
  1104. DWORD *lpw = (DWORD *)lpVertices;
  1105. for (i=0 ; i<dwNumVertices; i++)
  1106. {
  1107. DISPDBG((lvl,"Vertex # %d", i));
  1108. for (j=0; j < pContext->FVFData.dwStride; j+=4)
  1109. {
  1110. DISPDBG((lvl," 0x%08x",*lpw++));
  1111. }
  1112. }
  1113. } // DumpVertices
  1114. //-----------------------------------------------------------------------------
  1115. //
  1116. // DumpHexData
  1117. //
  1118. // Dumps hexadecimal data
  1119. //
  1120. //-----------------------------------------------------------------------------
  1121. void DumpHexData(int lvl,
  1122. LPBYTE lpData,
  1123. DWORD dwNumBytes)
  1124. {
  1125. DWORD i , iRemChars, iSlen;
  1126. DWORD *lpdw = (DWORD *)lpData;
  1127. char s[80] = "",m[80] = "";
  1128. iRemChars = 80;
  1129. for (i=0 ; i <= (dwNumBytes / sizeof(DWORD)); i++)
  1130. {
  1131. sprintf(s,"0x%08x ",*lpdw++);
  1132. iSlen = strlen(s);
  1133. if (iSlen < iRemChars)
  1134. {
  1135. strncat(m,s,iRemChars);
  1136. iRemChars -= iSlen;
  1137. }
  1138. if ( ((i % 6) == 5) ||
  1139. (i == (dwNumBytes / sizeof(DWORD))) )
  1140. {
  1141. DISPDBG((lvl,"%s",m));
  1142. s[0] = m[0] = '\0';
  1143. }
  1144. }
  1145. } // DumpVertices
  1146. //-----------------------------------------------------------------------------
  1147. //
  1148. // DumpDDSurface
  1149. //
  1150. // Dumps a LPDDRAWI_DDRAWSURFACE_LCL ( PDD_SURFACE_LOCAL on Win2K) structure
  1151. //
  1152. //-----------------------------------------------------------------------------
  1153. #define CAPS_REPORT(param) \
  1154. if (ddsCaps.dwCaps & DDSCAPS_##param) \
  1155. { \
  1156. DISPDBG((Level, " " #param)); \
  1157. }
  1158. #define CAPS_REPORT2(param) \
  1159. if (pSurface->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_##param) \
  1160. { \
  1161. DISPDBG((Level, " " #param)); \
  1162. }
  1163. void DumpDDSurface(int DebugLevel, LPDDRAWI_DDRAWSURFACE_LCL pSurface)
  1164. {
  1165. LPDDPIXELFORMAT pPixFormat;
  1166. P3_SURF_FORMAT* pFormatSurface = _DD_SUR_GetSurfaceFormat(pSurface);
  1167. DDSCAPS ddsCaps;
  1168. int Level = -100;
  1169. if (DebugLevel <= P3R3DX_DebugLevel)
  1170. {
  1171. DISPDBG((Level,"Surface Dump:"));
  1172. DISPDBG((Level,"Format: %s", pFormatSurface->pszStringFormat));
  1173. // Get the surface format
  1174. pPixFormat = DDSurf_GetPixelFormat(pSurface);
  1175. ddsCaps = pSurface->ddsCaps;
  1176. DISPDBG((Level, " Surface Width: 0x%x", pSurface->lpGbl->wWidth));
  1177. DISPDBG((Level, " Surface Height: 0x%x", pSurface->lpGbl->wHeight));
  1178. DISPDBG((Level, " Surface Pitch: 0x%x", pSurface->lpGbl->lPitch));
  1179. DISPDBG((Level, " ddsCaps.dwCaps: 0x%x", pSurface->ddsCaps.dwCaps));
  1180. DISPDBG((Level, " dwFlags: 0x%x", pSurface->dwFlags));
  1181. DISPDBG((Level, " Pixel Format:"));
  1182. DISPDBG((Level, " dwFourCC: 0x%x", pPixFormat->dwFourCC));
  1183. DISPDBG((Level, " dwRGBBitCount: 0x%x", pPixFormat->dwRGBBitCount));
  1184. DISPDBG((Level, " dwR/Y BitMask: 0x%x", pPixFormat->dwRBitMask));
  1185. DISPDBG((Level, " dwG/U BitMask: 0x%x", pPixFormat->dwGBitMask));
  1186. DISPDBG((Level, " dwB/V BitMask: 0x%x", pPixFormat->dwBBitMask));
  1187. DISPDBG((Level, " dwRGBAlphaBitMask: 0x%x", pPixFormat->dwRGBAlphaBitMask));
  1188. #ifndef WNT_DDRAW
  1189. DISPDBG((Level, " DestBlt: dwColorSpaceLowValue: 0x%x", pSurface->ddckCKDestBlt.dwColorSpaceLowValue));
  1190. DISPDBG((Level, " DestBlt: dwColorSpaceHighValue: 0x%x", pSurface->ddckCKDestBlt.dwColorSpaceHighValue));
  1191. DISPDBG((Level, " SrcBlt: dwColorSpaceLowValue: 0x%x", pSurface->ddckCKSrcBlt.dwColorSpaceLowValue));
  1192. DISPDBG((Level, " SrcBlt: dwColorSpaceHighValue: 0x%x", pSurface->ddckCKSrcBlt.dwColorSpaceHighValue));
  1193. #endif
  1194. DISPDBG((Level, " Surface Is:"));
  1195. CAPS_REPORT(TEXTURE);
  1196. CAPS_REPORT(PRIMARYSURFACE);
  1197. CAPS_REPORT(OFFSCREENPLAIN);
  1198. CAPS_REPORT(FRONTBUFFER);
  1199. CAPS_REPORT(BACKBUFFER);
  1200. CAPS_REPORT(COMPLEX);
  1201. CAPS_REPORT(FLIP);
  1202. CAPS_REPORT(OVERLAY);
  1203. CAPS_REPORT(MODEX);
  1204. CAPS_REPORT(ALLOCONLOAD);
  1205. CAPS_REPORT(LIVEVIDEO);
  1206. CAPS_REPORT(PALETTE);
  1207. CAPS_REPORT(SYSTEMMEMORY);
  1208. CAPS_REPORT(3DDEVICE);
  1209. CAPS_REPORT(VIDEOMEMORY);
  1210. CAPS_REPORT(VISIBLE);
  1211. CAPS_REPORT(MIPMAP);
  1212. // not supported in NT until we get NT5 (which will have DX5)
  1213. CAPS_REPORT(VIDEOPORT);
  1214. CAPS_REPORT(LOCALVIDMEM);
  1215. CAPS_REPORT(NONLOCALVIDMEM);
  1216. CAPS_REPORT(WRITEONLY);
  1217. if (pSurface->lpSurfMore)
  1218. {
  1219. CAPS_REPORT2(HARDWAREDEINTERLACE);
  1220. CAPS_REPORT2(HINTDYNAMIC);
  1221. CAPS_REPORT2(HINTSTATIC);
  1222. CAPS_REPORT2(TEXTUREMANAGE);
  1223. CAPS_REPORT2(OPAQUE);
  1224. CAPS_REPORT2(HINTANTIALIASING);
  1225. #if W95_DDRAW
  1226. CAPS_REPORT2(VERTEXBUFFER);
  1227. CAPS_REPORT2(COMMANDBUFFER);
  1228. #endif
  1229. }
  1230. if (pPixFormat->dwFlags & DDPF_ZBUFFER)
  1231. {
  1232. DISPDBG((Level," Z BUFFER"));
  1233. }
  1234. if (pPixFormat->dwFlags & DDPF_ALPHAPIXELS)
  1235. {
  1236. DISPDBG((Level," ALPHAPIXELS"));
  1237. }
  1238. // not supported in NT until we get NT5
  1239. if (pPixFormat->dwFlags & DDPF_LUMINANCE)
  1240. {
  1241. DISPDBG((Level," LUMINANCE"));
  1242. }
  1243. if (pPixFormat->dwFlags & DDPF_ALPHA)
  1244. {
  1245. DISPDBG((Level," ALPHA"));
  1246. }
  1247. }
  1248. } // DumpDDSurface
  1249. char *pcSimpleCapsString(DWORD dwCaps)
  1250. {
  1251. static char flags[5];
  1252. flags[0] = flags[1] = flags[2] = flags[3] = ' '; flags[4] = 0;
  1253. if(dwCaps & DDSCAPS_TEXTURE) flags[1] = 'T';
  1254. if(dwCaps & DDSCAPS_ZBUFFER) flags[2] = 'Z';
  1255. if(dwCaps & DDSCAPS_3DDEVICE) flags[3] = 'R';
  1256. if(dwCaps & DDSCAPS_VIDEOMEMORY)
  1257. {
  1258. flags[0] = 'V';
  1259. }
  1260. else if(dwCaps & DDSCAPS_NONLOCALVIDMEM)
  1261. {
  1262. flags[0] = 'A';
  1263. }
  1264. else
  1265. {
  1266. flags[0] = 'S';
  1267. }
  1268. return flags;
  1269. } // cSimpleCapsString
  1270. //-----------------------------------------------------------------------------
  1271. //
  1272. // DumpDDSurfaceDesc
  1273. //
  1274. // Dumps a DDSURFACEDESC structure
  1275. //
  1276. //-----------------------------------------------------------------------------
  1277. #define CAPS_REPORT_DESC(param) \
  1278. if (pDesc->ddsCaps.dwCaps & DDSCAPS_##param) \
  1279. { \
  1280. DISPDBG((Level, " " #param)); \
  1281. }
  1282. #define CAPS_REPORT_DESC2(param) \
  1283. if (((DDSURFACEDESC2*)pDesc)->ddsCaps.dwCaps2 & DDSCAPS2_##param) \
  1284. { \
  1285. DISPDBG((Level, " " #param)); \
  1286. }
  1287. void DumpDDSurfaceDesc(int DebugLevel, DDSURFACEDESC* pDesc)
  1288. {
  1289. DDPIXELFORMAT* pPixFormat = &pDesc->ddpfPixelFormat;
  1290. int Level = -100;
  1291. if (DebugLevel <= P3R3DX_DebugLevel)
  1292. {
  1293. DISPDBG((Level,"Surface Dump:"));
  1294. DISPDBG((Level, " Surface Width: 0x%x", pDesc->dwWidth));
  1295. DISPDBG((Level, " Surface Height: 0x%x", pDesc->dwHeight));
  1296. DISPDBG((Level, " ddsCaps.dwCaps: 0x%x", pDesc->ddsCaps.dwCaps));
  1297. DISPDBG((Level, " dwFlags: 0x%x", pDesc->dwFlags));
  1298. DISPDBG((Level, "Pixel Format:"));
  1299. DISPDBG((Level, " dwFourCC: 0x%x", pPixFormat->dwFourCC));
  1300. DISPDBG((Level, " dwRGBBitCount: 0x%x", pPixFormat->dwRGBBitCount));
  1301. DISPDBG((Level, " dwR/Y BitMask: 0x%x", pPixFormat->dwRBitMask));
  1302. DISPDBG((Level, " dwG/U BitMask: 0x%x", pPixFormat->dwGBitMask));
  1303. DISPDBG((Level, " dwB/V BitMask: 0x%x", pPixFormat->dwBBitMask));
  1304. DISPDBG((Level, " dwRGBAlphaBitMask: 0x%x", pPixFormat->dwRGBAlphaBitMask));
  1305. DISPDBG((Level, "Surface Is:"));
  1306. CAPS_REPORT_DESC(TEXTURE);
  1307. CAPS_REPORT_DESC(PRIMARYSURFACE);
  1308. CAPS_REPORT_DESC(OFFSCREENPLAIN);
  1309. CAPS_REPORT_DESC(FRONTBUFFER);
  1310. CAPS_REPORT_DESC(BACKBUFFER);
  1311. CAPS_REPORT_DESC(COMPLEX);
  1312. CAPS_REPORT_DESC(FLIP);
  1313. CAPS_REPORT_DESC(OVERLAY);
  1314. CAPS_REPORT_DESC(MODEX);
  1315. CAPS_REPORT_DESC(ALLOCONLOAD);
  1316. CAPS_REPORT_DESC(LIVEVIDEO);
  1317. CAPS_REPORT_DESC(PALETTE);
  1318. CAPS_REPORT_DESC(SYSTEMMEMORY);
  1319. CAPS_REPORT_DESC(3DDEVICE);
  1320. CAPS_REPORT_DESC(VIDEOMEMORY);
  1321. CAPS_REPORT_DESC(VISIBLE);
  1322. CAPS_REPORT_DESC(MIPMAP);
  1323. CAPS_REPORT_DESC(VIDEOPORT);
  1324. CAPS_REPORT_DESC(LOCALVIDMEM);
  1325. CAPS_REPORT_DESC(NONLOCALVIDMEM);
  1326. CAPS_REPORT_DESC(STANDARDVGAMODE);
  1327. CAPS_REPORT_DESC(OPTIMIZED);
  1328. CAPS_REPORT_DESC(EXECUTEBUFFER);
  1329. CAPS_REPORT_DESC(WRITEONLY);
  1330. if (pDesc->dwSize == sizeof(DDSURFACEDESC2))
  1331. {
  1332. CAPS_REPORT_DESC2(HARDWAREDEINTERLACE);
  1333. CAPS_REPORT_DESC2(HINTDYNAMIC);
  1334. CAPS_REPORT_DESC2(HINTSTATIC);
  1335. CAPS_REPORT_DESC2(TEXTUREMANAGE);
  1336. CAPS_REPORT_DESC2(OPAQUE);
  1337. CAPS_REPORT_DESC2(HINTANTIALIASING);
  1338. #if W95_DDRAW
  1339. CAPS_REPORT_DESC2(VERTEXBUFFER);
  1340. CAPS_REPORT_DESC2(COMMANDBUFFER);
  1341. #endif
  1342. }
  1343. if (pPixFormat->dwFlags & DDPF_ZBUFFER)
  1344. {
  1345. DISPDBG((Level," Z BUFFER"));
  1346. }
  1347. if (pPixFormat->dwFlags & DDPF_ALPHAPIXELS)
  1348. {
  1349. DISPDBG((Level," ALPHAPIXELS"));
  1350. }
  1351. if (pPixFormat->dwFlags & DDPF_ALPHA)
  1352. {
  1353. DISPDBG((Level," ALPHA"));
  1354. }
  1355. }
  1356. }
  1357. //-----------------------------------------------------------------------------
  1358. //
  1359. // DumpDP2Flags
  1360. //
  1361. // Dumps the meaning of the D3D DrawPrimitives2 flags
  1362. //
  1363. //-----------------------------------------------------------------------------
  1364. void
  1365. DumpDP2Flags( DWORD lvl, DWORD flags )
  1366. {
  1367. if( flags & D3DHALDP2_USERMEMVERTICES )
  1368. DISPDBG((lvl, " USERMEMVERTICES" ));
  1369. if( flags & D3DHALDP2_EXECUTEBUFFER )
  1370. DISPDBG((lvl, " EXECUTEBUFFER" ));
  1371. if( flags & D3DHALDP2_SWAPVERTEXBUFFER )
  1372. DISPDBG((lvl, " SWAPVERTEXBUFFER" ));
  1373. if( flags & D3DHALDP2_SWAPCOMMANDBUFFER )
  1374. DISPDBG((lvl, " SWAPCOMMANDBUFFER" ));
  1375. if( flags & D3DHALDP2_REQVERTEXBUFSIZE )
  1376. DISPDBG((lvl, " REQVERTEXBUFSIZE" ));
  1377. if( flags & D3DHALDP2_REQCOMMANDBUFSIZE )
  1378. DISPDBG((lvl, " REQCOMMANDBUFSIZE" ));
  1379. } // DumpDP2Flags
  1380. //-----------------------------------------------------------------------------
  1381. //
  1382. // ********************** LOW LEVEL DEBUGGING SUPPORT ************************
  1383. //
  1384. //-----------------------------------------------------------------------------
  1385. LONG P3R3DX_DebugLevel = 0;
  1386. #if W95_DDRAW
  1387. void DebugRIP()
  1388. {
  1389. _asm int 1;
  1390. }
  1391. #endif // W95_DDRAW
  1392. static char *BIG = "<+/-large_float>";
  1393. #if defined(_X86_)
  1394. void
  1395. expandFloats(char *flts, char *format, va_list argp)
  1396. {
  1397. int ch;
  1398. double f;
  1399. unsigned int ip, fp;
  1400. int *ap = (int *)argp;
  1401. int *dp = ap;
  1402. while (ch = *format++) {
  1403. if (ch == '%') {
  1404. ch = *format++; // Get the f, s, c, i, d, x etc...
  1405. if (!ch)
  1406. return; // If someone foolishly gave me "hello %"
  1407. switch (ch) {
  1408. case 'f':
  1409. case 'g':
  1410. case 'e':
  1411. // Here we have a double that needs
  1412. // replacing with a string equivalent.
  1413. f = *(double *)ap;
  1414. *(format - 1) = 's'; // Tell it to get a string next time!
  1415. *((char **)dp) = flts; // This is where I'll put the string
  1416. ap += 2; // Skip the double in the source
  1417. dp++; // Skip the new string pointer
  1418. if (f < 0)
  1419. {
  1420. *flts++ = '-';
  1421. f = -f;
  1422. }
  1423. if (f > LONG_MAX)
  1424. {
  1425. *((char **)ap - 2) = BIG;
  1426. break;
  1427. }
  1428. myFtoi((int*)&ip, (float)f);
  1429. // The state of the floating point flags is indeterminate here.
  1430. // You may get truncation which you want, you may get rounding,
  1431. // which you don't want.
  1432. if (ip > f)
  1433. {
  1434. // rounding will have made (ip = f+1) sometimes
  1435. ip -= 1;
  1436. }
  1437. {
  1438. double fTemp = ((f * 1e6) - (ip * 1e6));
  1439. myFtoi((int*)&fp, (float)fTemp);
  1440. }
  1441. #if W95_DDRAW
  1442. wsprintf(flts, "%u.%06u", ip, fp);
  1443. #endif
  1444. flts += 1 + strlen(flts); // advance the pointer to where
  1445. // the next float will be expanded
  1446. break;
  1447. case '%':
  1448. break;
  1449. default:
  1450. *dp++ = *ap++; // copy the argument (down) the list
  1451. break;
  1452. }
  1453. }
  1454. }
  1455. } // expandFloats()
  1456. #else
  1457. void
  1458. expandFloats(char *flts, char *format, va_list argp)
  1459. {
  1460. // do nothing if it's not _X86_
  1461. }
  1462. #endif // defined(_X86_)
  1463. #ifdef WNT_DDRAW
  1464. void Drv_strcpy(char *szDest, char *szSrc)
  1465. {
  1466. do
  1467. {
  1468. *szDest++ = *szSrc++;
  1469. } while (*szSrc != 0);
  1470. *szDest = '\0';
  1471. }
  1472. void __cdecl DebugPrintNT(LONG DebugPrintLevel, PCHAR DebugMessage, ...)
  1473. {
  1474. char floatstr[256];
  1475. char szFormat[256];
  1476. va_list ap;
  1477. va_start(ap, DebugMessage);
  1478. CheckChipErrorFlags();
  1479. if (DebugPrintLevel <= P3R3DX_DebugLevel)
  1480. {
  1481. Drv_strcpy(szFormat, DebugMessage);
  1482. expandFloats(floatstr, szFormat, ap);
  1483. EngDebugPrint("PERM3DD: ", szFormat, ap);
  1484. EngDebugPrint("", "\n", ap);
  1485. }
  1486. va_end(ap);
  1487. } // DebugPrint()
  1488. #else
  1489. #define START_STR "DX"
  1490. #define END_STR ""
  1491. //
  1492. // DebugPrint
  1493. //
  1494. // display a debug message
  1495. //
  1496. void __cdecl DebugPrint(LONG DebugLevelPrint, LPSTR format, ... )
  1497. {
  1498. char str[256];
  1499. char floatstr[256];
  1500. char szFormat[256];
  1501. va_list ap;
  1502. va_start(ap, format);
  1503. // If you set the debug level negative then you don't check the error
  1504. // flags - this lets an optimised debug build run quicker
  1505. if( P3R3DX_DebugLevel >= 0 )
  1506. {
  1507. CheckChipErrorFlags();
  1508. }
  1509. if (DebugLevelPrint <= P3R3DX_DebugLevel)
  1510. {
  1511. // Take a copy of the format string so that I can change "%f" to "%s".
  1512. lstrcpy(szFormat, format);
  1513. expandFloats(floatstr, szFormat, ap);
  1514. if (g_pThisTemp)
  1515. {
  1516. wsprintf((LPSTR)str, "%s(%d): ",
  1517. START_STR,
  1518. (int)g_pThisTemp->pGLInfo->dwCurrentContext);
  1519. }
  1520. else
  1521. {
  1522. wsprintf((LPSTR)str, "%s: 0 ", START_STR);
  1523. }
  1524. wvsprintf(str + strlen(START_STR) + 7, szFormat, ap);
  1525. wsprintf( str + strlen( str ), "%s", "\r\n" );
  1526. OutputDebugString( str );
  1527. }
  1528. va_end(ap);
  1529. } // DebugPrint
  1530. #endif // WNT_DDRAW
  1531. //-----------------------------------------------------------------------------
  1532. //
  1533. // ****************** HARDWARE DEPENDENT DEBUGGING SUPPORT *******************
  1534. //
  1535. //-----------------------------------------------------------------------------
  1536. P3_THUNKEDDATA* g_pThisTemp = NULL;
  1537. BOOL g_bDetectedFIFOError = FALSE;
  1538. BOOL CheckFIFOEntries(DWORD Count)
  1539. {
  1540. if (g_pThisTemp)
  1541. {
  1542. if (!g_bDetectedFIFOError)
  1543. {
  1544. g_pThisTemp->EntriesLeft -= Count;
  1545. g_pThisTemp->DMAEntriesLeft -= Count;
  1546. // TURN_ON_DISCONNECT will set Entries left to -20000
  1547. if ( ( (signed)g_pThisTemp->EntriesLeft < 0 ) &&
  1548. ( (signed)g_pThisTemp->EntriesLeft > -10000 ) )
  1549. {
  1550. g_bDetectedFIFOError = TRUE;
  1551. return TRUE;
  1552. }
  1553. // Disconnects are irrelevant to DMA buffers.
  1554. if ( ( (signed)g_pThisTemp->DMAEntriesLeft < 0 ) &&
  1555. ( (signed)g_pThisTemp->DMAEntriesLeft > -10000 ) )
  1556. {
  1557. g_bDetectedFIFOError = TRUE;
  1558. return TRUE;
  1559. }
  1560. }
  1561. }
  1562. return FALSE;
  1563. } // CheckFIFOEntries
  1564. #ifdef WNT_DDRAW
  1565. void
  1566. CheckChipErrorFlags()
  1567. {
  1568. char Buff[100];
  1569. if (g_pThisTemp != NULL)
  1570. {
  1571. P3_THUNKEDDATA* pThisDisplay = g_pThisTemp;
  1572. DWORD _temp_ul;
  1573. DWORD _temp_ul2;
  1574. _temp_ul = READ_GLINT_CTRL_REG(ErrorFlags);
  1575. _temp_ul2 = READ_GLINT_CTRL_REG(DeltaErrorFlags);
  1576. _temp_ul |= _temp_ul2;
  1577. _temp_ul &= ~0x2; // we're not interested in output fifo errors
  1578. _temp_ul &= ~0x10; // ignore any Video FIFO underrun errors on P2
  1579. _temp_ul &= ~0x2000; // ignore any host-in DMA errors
  1580. if (_temp_ul != 0)
  1581. {
  1582. // DISPDBG((-1000, "PERM3DD: %s", Buff));
  1583. //EngDebugBreak();
  1584. LOAD_GLINT_CTRL_REG(ErrorFlags, _temp_ul);
  1585. LOAD_GLINT_CTRL_REG(DeltaErrorFlags, _temp_ul);
  1586. }
  1587. }
  1588. } // CheckChipErrorFlags()
  1589. #else
  1590. void
  1591. CheckChipErrorFlags()
  1592. {
  1593. DWORD dw;
  1594. char buff[64];
  1595. if (!g_pThisTemp) return;
  1596. if (!g_pThisTemp->pGLInfo) return;
  1597. // Only check the error flags if we aren't DMA'ing.
  1598. if (!(g_pThisTemp->pGLInfo->GlintBoardStatus & GLINT_DMA_COMPLETE)) return;
  1599. if (g_pThisTemp->pGlint) {
  1600. dw = g_pThisTemp->pGlint->ErrorFlags & ~0x10;
  1601. if (dw & (dw != 2)) {
  1602. wsprintf(buff, "** Render Chip Error ** [0x%X]!\r\n", dw);
  1603. OutputDebugString(buff);
  1604. g_pThisTemp->pGlint->ErrorFlags = dw;
  1605. OutputDebugString("** Cleared... **\r\n");
  1606. DebugRIP();
  1607. }
  1608. dw = g_pThisTemp->pGlint->DeltaErrorFlags & ~0x10;
  1609. if (dw & (dw != 2)) {
  1610. wsprintf(buff, "** Delta Error ** [0x%X]!\r\n", dw);
  1611. OutputDebugString(buff);
  1612. g_pThisTemp->pGlint->DeltaErrorFlags = dw;
  1613. OutputDebugString("** Cleared... **\r\n");
  1614. DebugRIP();
  1615. }
  1616. }
  1617. } // CheckChipErrorFlags()
  1618. #endif // WNT_DDRAW
  1619. void
  1620. ColorArea(
  1621. ULONG_PTR pBuffer,
  1622. DWORD dwWidth,
  1623. DWORD dwHeight,
  1624. DWORD dwPitch,
  1625. int iBitDepth,
  1626. DWORD dwValue)
  1627. {
  1628. DWORD CountY;
  1629. DWORD CountX;
  1630. switch (iBitDepth)
  1631. {
  1632. case __GLINT_8BITPIXEL:
  1633. {
  1634. for (CountY = 0; CountY < dwHeight; CountY++)
  1635. {
  1636. BYTE* pCurrentPixel = (BYTE*)pBuffer;
  1637. for (CountX = 0; CountX < dwWidth; CountX++)
  1638. {
  1639. *pCurrentPixel++ = (BYTE)dwValue;
  1640. }
  1641. pBuffer += dwPitch;
  1642. }
  1643. }
  1644. break;
  1645. case __GLINT_16BITPIXEL:
  1646. {
  1647. for (CountY = 0; CountY < dwHeight; CountY++)
  1648. {
  1649. WORD* pCurrentPixel = (WORD*)pBuffer;
  1650. for (CountX = 0; CountX < dwWidth; CountX++)
  1651. {
  1652. *pCurrentPixel++ = (WORD)dwValue;
  1653. }
  1654. pBuffer += dwPitch;
  1655. }
  1656. }
  1657. break;
  1658. case __GLINT_32BITPIXEL:
  1659. case __GLINT_24BITPIXEL:
  1660. {
  1661. for (CountY = 0; CountY < dwHeight; CountY++)
  1662. {
  1663. DWORD* pCurrentPixel = (DWORD*)pBuffer;
  1664. for (CountX = 0; CountX < dwWidth; CountX++)
  1665. {
  1666. *pCurrentPixel++ = (DWORD)dwValue;
  1667. }
  1668. pBuffer += dwPitch;
  1669. }
  1670. }
  1671. break;
  1672. }
  1673. } // ColorArea
  1674. //@@BEGIN_DDKSPLIT
  1675. static int unitsBits[] = {
  1676. 13, 12, 11, 10,
  1677. 3, 2, 8, 7,
  1678. 18, 15, 14, 6,
  1679. 5, 1, 0
  1680. };
  1681. static char *unitNames[] = {
  1682. "HostOut", "FBWrite", "LogicOp", "Dither",
  1683. "Texture/Fog/Blend", "ColourDDA", "FBRead", "LBWrite",
  1684. "YUV", "TextureRead", "TextureAddress", "StencilDepth",
  1685. "LBRead", "Scissor/Stipple", "Rasterizer"
  1686. };
  1687. #define NUM_UNITS (sizeof(unitsBits) / sizeof(unitsBits[0]))
  1688. void
  1689. DisableChipUnits()
  1690. {
  1691. int i, count;
  1692. DWORD inSpace = g_pThisTemp->pGlint->InFIFOSpace;
  1693. BOOL helped = FALSE;
  1694. volatile DWORD *testReg;
  1695. volatile DWORD *addrMode = &g_pThisTemp->pGlint->TextureAddressMode;
  1696. DISPDBG((ERRLVL, "TextureAddressMode = 0x%08X", *addrMode));
  1697. i = 0;
  1698. testReg = &g_pThisTemp->pGlint->TestRegister;
  1699. for (count = 0; count < NUM_UNITS; count++) {
  1700. i = 1L << unitsBits[count];
  1701. *testReg = i;
  1702. *testReg = 0;
  1703. *testReg = i;
  1704. *testReg = 0;
  1705. if (inSpace != g_pThisTemp->pGlint->InFIFOSpace) {
  1706. DISPDBG((ERRLVL, "Chip unlocked by disabling unit \"%s\"", unitNames[count]));
  1707. helped = TRUE;
  1708. inSpace = g_pThisTemp->pGlint->InFIFOSpace;
  1709. }
  1710. }
  1711. if (helped) {
  1712. DISPDBG((ERRLVL, "Which helped..."));
  1713. } else {
  1714. DISPDBG((ERRLVL, "Chip still locked"));
  1715. *testReg = ~0UL;
  1716. *testReg = 0;
  1717. *testReg = ~0UL;
  1718. *testReg = 0;
  1719. if (inSpace == g_pThisTemp->pGlint->InFIFOSpace) {
  1720. DISPDBG((ERRLVL, "Writing -1 didn't help"));
  1721. } else {
  1722. DISPDBG((ERRLVL, "BUT! Writing -1 frees some space..."));
  1723. }
  1724. }
  1725. DISPDBG((ERRLVL, "TextureAddressMode = 0x%08X", *addrMode));
  1726. } // DisableChipUnits()
  1727. #if 0
  1728. StatRecord stats[LAST_STAT + 2] = {
  1729. {"Locks ", 0, 0},
  1730. {"TextureChanges", 0, 0},
  1731. {"D3DSynchs ", 0, 0},
  1732. {"StateChanges ", 0, 0},
  1733. {"...no change ", 0, 0},
  1734. {"Blits ", 0, 0},
  1735. {"DMA Buffers ", 0, 0},
  1736. {"DMA DWORDS ", 0, 0},
  1737. {"DMA time > CPU", 0, 0},
  1738. {"CPU time > DMA", 0, 0},
  1739. {"Wait on DMA ", 0, 0},
  1740. {"Execute ", 0, 0},
  1741. {"Tris ", 0, 0},
  1742. {"FF Tris ", 0, 0},
  1743. {"Vanilla Render", 0, 0},
  1744. {"Points ", 0, 0},
  1745. {"Lines ", 0, 0},
  1746. {"DPrm TFans ", 0, 0},
  1747. {"DPrm TStrps ", 0, 0},
  1748. {"DPrm TLists ", 0, 0},
  1749. {"DPrm TFansIdx ", 0, 0},
  1750. {"DPrm TStrpsIdx", 0, 0},
  1751. {"DPrm TListsIdx", 0, 0},
  1752. {"Total vertices", 0, 0},
  1753. {"...cached ", 0, 0},
  1754. {"Alpha strips ", 0, 0},
  1755. {"Mip strips ", 0, 0},
  1756. {"VALIDATEDEVICE", 0, 0},
  1757. // Add any extras just in front of this comment
  1758. {"**scene no** ", 0, 0},
  1759. {"**flip count**", 0, 0}
  1760. };
  1761. #endif
  1762. //@@END_DDKSPLIT
  1763. const char *getTagString( GlintDataPtr glintInfo, ULONG tag ) {
  1764. return p3r3TagString( tag & ((1 << 12) - 1) );
  1765. }
  1766. #endif // DBG