home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / system / source / debug.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  6.9 KB  |  291 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #include "stdafx.h"
  27. #include <stdio.h>
  28.  
  29. #include <windows.h>
  30. #include <intrin.h>
  31.  
  32. #include <vd2/system/vdtypes.h>
  33. #include <vd2/system/cpuaccel.h>
  34. #include <vd2/system/debug.h>
  35. #include <vd2/system/thread.h>
  36.  
  37. #ifdef _DEBUG
  38.  
  39. class VDSafeMessageBoxThreadW32 : public VDThread {
  40. public:
  41.     VDSafeMessageBoxThreadW32(HWND hwndParent, const char *pszText, const char *pszCaption, DWORD dwFlags)
  42.         : mhwndParent(hwndParent)
  43.         , mpszText(pszText)
  44.         , mpszCaption(pszCaption)
  45.         , mdwFlags(dwFlags)
  46.     {
  47.     }
  48.  
  49.     DWORD GetResult() const { return mdwResult; }
  50.  
  51. protected:
  52.     void ThreadRun() {
  53.         mdwResult = MessageBox(mhwndParent, mpszText, mpszCaption, mdwFlags);
  54.     }
  55.  
  56.     HWND mhwndParent;
  57.     const char *const mpszText;
  58.     const char *const mpszCaption;
  59.     const DWORD mdwFlags;
  60.     DWORD mdwResult;
  61. };
  62.  
  63. UINT VDSafeMessageBoxW32(HWND hwndParent, const char *pszText, const char *pszCaption, DWORD dwFlags) {
  64.     VDSafeMessageBoxThreadW32 mbox(hwndParent, pszText, pszCaption, dwFlags);
  65.  
  66.     mbox.ThreadStart();
  67.     mbox.ThreadWait();
  68.     return mbox.GetResult();
  69. }
  70.  
  71. VDAssertResult VDAssert(const char *exp, const char *file, int line) {
  72.     DWORD dwOldError = GetLastError();
  73.     char szText[1024];
  74.  
  75.     VDDEBUG("%s(%d): Assert failed: %s\n", file, line, exp);
  76.  
  77.     wsprintf(szText,
  78.         "Assert failed in module %s, line %d:\n"
  79.         "\n"
  80.         "\t%s\n"
  81.         "\n"
  82.         "Break into debugger?", file, line, exp);
  83.  
  84.     UINT result = VDSafeMessageBoxW32(NULL, szText, "Assert failure", MB_ABORTRETRYIGNORE|MB_ICONWARNING|MB_TASKMODAL);
  85.  
  86.     SetLastError(dwOldError);
  87.  
  88.     switch(result) {
  89.     case IDABORT:
  90.         ::Sleep(250);                // Pause for a moment so the VC6 debugger doesn't freeze.
  91.         return kVDAssertBreak;
  92.     case IDRETRY:
  93.         return kVDAssertContinue;
  94.     default:
  95.         VDNEVERHERE;
  96.     case IDIGNORE:
  97.         return kVDAssertIgnore;
  98.     }
  99. }
  100.  
  101. VDAssertResult VDAssertPtr(const char *exp, const char *file, int line) {
  102.     DWORD dwOldError = GetLastError();
  103.     char szText[1024];
  104.  
  105.     VDDEBUG("%s(%d): Assert failed: %s is not a valid pointer\n", file, line, exp);
  106.  
  107.     wsprintf(szText,
  108.         "Assert failed in module %s, line %d:\n"
  109.         "\n"
  110.         "\t(%s) not a valid pointer\n"
  111.         "\n"
  112.         "Break into debugger?", file, line, exp);
  113.  
  114.     UINT result = VDSafeMessageBoxW32(NULL, szText, "Assert failure", MB_ABORTRETRYIGNORE|MB_ICONWARNING|MB_TASKMODAL);
  115.  
  116.     SetLastError(dwOldError);
  117.  
  118.     switch(result) {
  119.     case IDABORT:
  120.         return kVDAssertBreak;
  121.     case IDRETRY:
  122.         return kVDAssertContinue;
  123.     default:
  124.         VDNEVERHERE;
  125.     case IDIGNORE:
  126.         return kVDAssertIgnore;
  127.     }
  128. }
  129.  
  130. #endif
  131.  
  132. void VDProtectedAutoScopeICLWorkaround() {}
  133.  
  134. void VDDebugPrint(const char *format, ...) {
  135.     char buf[4096];
  136.  
  137.     va_list val;
  138.     va_start(val, format);
  139.     _vsnprintf(buf, sizeof buf, format, val);
  140.     va_end(val);
  141.     Sleep(0);
  142.     OutputDebugString(buf);
  143. }
  144.  
  145. ///////////////////////////////////////////////////////////////////////////
  146.  
  147. namespace {
  148.     IVDExternalCallTrap *g_pExCallTrap;
  149. }
  150.  
  151. void VDSetExternalCallTrap(IVDExternalCallTrap *trap) {
  152.     g_pExCallTrap = trap;
  153. }
  154.  
  155. #if defined(WIN32) && defined(_M_IX86)
  156.     namespace {
  157.         bool IsFPUStateOK(unsigned& ctlword) {
  158.             ctlword = 0;
  159.  
  160.             __asm mov eax, ctlword
  161.             __asm fnstcw [eax]
  162.  
  163.             ctlword &= 0x0f3f;
  164.  
  165.             return ctlword == 0x023f;
  166.         }
  167.  
  168.         void ResetFPUState() {
  169.             static const unsigned ctlword = 0x027f;
  170.  
  171.             __asm fnclex
  172.             __asm fldcw ctlword
  173.         }
  174.  
  175.         bool IsSSEStateOK(uint32& ctlword) {
  176.             ctlword = _mm_getcsr();
  177.  
  178.             // Intel C/C++ flips FTZ and DAZ. :(
  179.             return (ctlword & 0x7f80) == 0x1f80;
  180.         }
  181.  
  182.         void ResetSSEState() {
  183.             _mm_setcsr(0x1f80);
  184.         }
  185.     }
  186.  
  187.     bool IsMMXState() {
  188.         char    buf[28];
  189.         unsigned short tagword;
  190.  
  191.         __asm fnstenv buf        // this resets the FPU control word somehow!?
  192.  
  193.         tagword = *(unsigned short *)(buf + 8);
  194.  
  195.         return (tagword != 0xffff);
  196.     }
  197.     void ClearMMXState() {
  198.         if (MMX_enabled)
  199.             __asm emms
  200.         else {
  201.             __asm {
  202.                 ffree st(0)
  203.                 ffree st(1)
  204.                 ffree st(2)
  205.                 ffree st(3)
  206.                 ffree st(4)
  207.                 ffree st(5)
  208.                 ffree st(6)
  209.                 ffree st(7)
  210.             }
  211.         }
  212.     }
  213.  
  214.     void VDClearEvilCPUStates() {
  215.         ResetFPUState();
  216.         ClearMMXState();
  217.     }
  218.  
  219.     void VDPreCheckExternalCodeCall(const char *file, int line) {
  220.         unsigned fpucw;
  221.         uint32 mxcsr;
  222.         bool bFPUStateBad = !IsFPUStateOK(fpucw);
  223.         bool bSSEStateBad = SSE_enabled && !IsSSEStateOK(mxcsr);
  224.         bool bMMXStateBad = IsMMXState();
  225.  
  226.         if (bMMXStateBad || bFPUStateBad || bSSEStateBad) {
  227.             ClearMMXState();
  228.             ResetFPUState();
  229.             if (SSE_enabled)
  230.                 ResetSSEState();
  231.         }
  232.  
  233.         if (g_pExCallTrap) {
  234.             if (bMMXStateBad)
  235.                 g_pExCallTrap->OnMMXTrap(NULL, file, line);
  236.  
  237.             if (bFPUStateBad)
  238.                 g_pExCallTrap->OnFPUTrap(NULL, file, line, fpucw);
  239.  
  240.             if (bSSEStateBad)
  241.                 g_pExCallTrap->OnSSETrap(NULL, file, line, mxcsr);
  242.         }
  243.     }
  244.  
  245.     void VDPostCheckExternalCodeCall(const wchar_t *mpContext, const char *mpFile, int mLine) {
  246.         unsigned fpucw;
  247.         uint32 mxcsr;
  248.         bool bFPUStateBad = !IsFPUStateOK(fpucw);
  249.         bool bSSEStateBad = SSE_enabled && !IsSSEStateOK(mxcsr);
  250.         bool bMMXStateBad = IsMMXState();
  251.         bool bBadState = bMMXStateBad || bFPUStateBad || bSSEStateBad;
  252.  
  253.         if (bBadState) {
  254.             ClearMMXState();
  255.             ResetFPUState();
  256.             if (SSE_enabled)
  257.                 ResetSSEState();
  258.         }
  259.  
  260.         if (g_pExCallTrap) {
  261.             if (bMMXStateBad)
  262.                 g_pExCallTrap->OnMMXTrap(mpContext, mpFile, mLine);
  263.  
  264.             if (bFPUStateBad)
  265.                 g_pExCallTrap->OnFPUTrap(mpContext, mpFile, mLine, fpucw);
  266.  
  267.             if (bSSEStateBad)
  268.                 g_pExCallTrap->OnSSETrap(mpContext, mpFile, mLine, mxcsr);
  269.         }
  270.     }
  271.  
  272. #else
  273.  
  274.     bool IsMMXState() {
  275.         return false;
  276.     }
  277.  
  278.     void ClearMMXState() {
  279.     }
  280.  
  281.     void VDClearEvilCPUStates() {
  282.     }
  283.  
  284.     void VDPreCheckExternalCodeCall(const char *file, int line) {
  285.     }
  286.  
  287.     void VDPostCheckExternalCodeCall(const wchar_t *mpContext, const char *mpFile, int mLine) {
  288.     }
  289.  
  290. #endif
  291.