home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / misc / misc.c < prev    next >
C/C++ Source or Header  |  1997-07-14  |  18KB  |  596 lines

  1. /*
  2.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  3.  *
  4.  *  File: misc.c
  5.  *
  6.  *  Miscellaneous functions not involving DD and D3D.  Part of D3DApp.
  7.  *
  8.  *  D3DApp is a collection of helper functions for Direct3D applications.
  9.  *  D3DApp consists of the following files:
  10.  *    d3dapp.h    Main D3DApp header to be included by application
  11.  *      d3dappi.h   Internal header
  12.  *      d3dapp.c    D3DApp functions seen by application.
  13.  *      ddcalls.c   All calls to DirectDraw objects except textures
  14.  *      d3dcalls.c  All calls to Direct3D objects except textures
  15.  *      texture.c   Texture loading and managing texture list
  16.  *      misc.c        Miscellaneous calls
  17.  */
  18.  
  19. #include "d3dappi.h"
  20. #include <stdarg.h>
  21.  
  22. /***************************************************************************/
  23. /*                          Setting Defaults                               */
  24. /***************************************************************************/
  25. /*
  26.  * D3DAppISetDefaults
  27.  * Set all the global variables to their default values.  Do not reset the
  28.  * image files.
  29.  */
  30. void
  31. D3DAppISetDefaults(void)
  32. {
  33.     int n;
  34.     char backup[D3DAPP_MAXTEXTURES][50];
  35.  
  36.     n = d3dappi.NumTextures;
  37.     memcpy(&backup[0][0], &d3dappi.ImageFile[0][0], 50 * D3DAPP_MAXTEXTURES);
  38.     ZEROMEM(d3dappi);
  39.     memcpy(&d3dappi.ImageFile[0][0], &backup[0][0], 50 * D3DAPP_MAXTEXTURES);
  40.     d3dappi.NumTextures = n;
  41.     d3dappi.bAppActive = TRUE;
  42.     ZEROMEM(d3dapprs);
  43.     d3dapprs.bZBufferOn = TRUE;
  44.     d3dapprs.bPerspCorrect = FALSE;
  45.     d3dapprs.ShadeMode = D3DSHADE_GOURAUD;
  46.     d3dapprs.TextureFilter = D3DFILTER_NEAREST;
  47.     d3dapprs.TextureBlend = D3DTBLEND_MODULATE;
  48.     d3dapprs.FillMode = D3DFILL_SOLID;
  49.     d3dapprs.bDithering = FALSE;
  50.     d3dapprs.bSpecular = TRUE;
  51.     d3dapprs.bAntialiasing = FALSE;
  52.     d3dapprs.bFogEnabled = FALSE;
  53.     d3dapprs.FogColor = RGB_MAKE(0, 0, 0);
  54.     d3dapprs.FogMode = D3DFOG_LINEAR;
  55.     d3dapprs.FogStart = D3DVAL(6.0);
  56.     d3dapprs.FogEnd = D3DVAL(11.0);
  57.  
  58.     lpClipper = NULL;
  59.     lpPalette = NULL;
  60.     bPrimaryPalettized = FALSE;
  61.     bPaletteActivate = FALSE;
  62.     bIgnoreWM_SIZE = FALSE;
  63.     ZEROMEM(ppe);
  64.     ZEROMEM(Originalppe);
  65.     LastError = DD_OK;
  66.     ZEROMEM(LastErrorString);
  67.     D3DDeviceDestroyCallback = NULL;
  68.     D3DDeviceDestroyCallbackContext = NULL;
  69.     D3DDeviceCreateCallback = NULL;
  70.     D3DDeviceCreateCallbackContext = NULL;
  71. }
  72.  
  73. /***************************************************************************/
  74. /*                Calling Device Create And Destroy Callbacks              */
  75. /***************************************************************************/
  76. BOOL
  77. D3DAppICallDeviceDestroyCallback(void)
  78. {
  79.     if (D3DDeviceDestroyCallback) {
  80.     if (CallbackRefCount) {
  81.         --CallbackRefCount;
  82.         return (D3DDeviceDestroyCallback)(D3DDeviceDestroyCallbackContext);
  83.     }
  84.     }
  85.     return TRUE;
  86. }
  87.  
  88. BOOL
  89. D3DAppICallDeviceCreateCallback(int w, int h)
  90. {
  91.     if (D3DDeviceCreateCallback) {
  92.     ++CallbackRefCount;
  93.     return (D3DDeviceCreateCallback)(w, h, &d3dappi.lpD3DViewport,
  94.                      D3DDeviceCreateCallbackContext);
  95.     }
  96.     return TRUE;
  97. }
  98.  
  99. /***************************************************************************/
  100. /*            Choosing and verifying the driver and display mode           */
  101. /***************************************************************************/
  102. /*
  103.  * D3DAppIPickDriver
  104.  * Choose a driver from the list of available drivers which can render to one
  105.  * of the given depths.  Hardware is prefered.  Mono-lighting drivers are
  106.  * prefered over RGB.
  107.  */
  108. BOOL
  109. D3DAppIPickDriver(int* driver, DWORD depths)
  110. {
  111.     int i, j;
  112.     j = 0;
  113.     for (i = 0; i < d3dappi.NumDrivers; i++)
  114.     if (d3dappi.Driver[i].Desc.dwDeviceRenderBitDepth & depths)
  115.         break;
  116.     if (i >= d3dappi.NumDrivers) {
  117.     *driver = D3DAPP_BOGUS;
  118.     return TRUE;
  119.     }
  120.     j = i;
  121.     for (i = 0; i < d3dappi.NumDrivers; i++) {
  122.     if (d3dappi.Driver[i].Desc.dwDeviceRenderBitDepth & depths) {
  123.         if (d3dappi.Driver[i].bIsHardware &&
  124.                           !d3dappi.Driver[j].bIsHardware)
  125.                               j = i;
  126.         else if (d3dappi.Driver[i].bIsHardware ==
  127.                          d3dappi.Driver[j].bIsHardware) {
  128.         if (d3dappi.Driver[i].Desc.dcmColorModel & D3DCOLOR_MONO &&
  129.             !(d3dappi.Driver[j].Desc.dcmColorModel & D3DCOLOR_MONO))
  130.             j = i;
  131.         }
  132.     }
  133.     }
  134.     if (j >= d3dappi.NumDrivers)
  135.     *driver = D3DAPP_BOGUS;
  136.     else
  137.     *driver = j;
  138.     return TRUE;
  139. }
  140.  
  141. /*
  142.  * D3DAppIFilterDisplayModes
  143.  * Set the bThisDriverCanDo flag for each display mode if the given driver
  144.  * can render in that depth.  Also checks to make sure there is enough
  145.  * total video memory for front/back/z-buffer in video memory if it's a
  146.  * hardware device.
  147.  */
  148. BOOL
  149. D3DAppIFilterDisplayModes(int driver)
  150. {
  151.     int i;
  152.     DWORD depths = d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth;
  153.  
  154.     for (i = 0; i < d3dappi.NumModes; i++) {
  155.     d3dappi.Mode[i].bThisDriverCanDo = FALSE;
  156.     if (!(D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths))
  157.         continue;
  158.     d3dappi.Mode[i].bThisDriverCanDo = TRUE;
  159.         
  160.     }
  161.     d3dappi.ThisMode.bThisDriverCanDo =
  162.                  d3dappi.Mode[d3dappi.CurrMode].bThisDriverCanDo;
  163.     return TRUE;
  164. }
  165.  
  166. /*
  167.  * D3DAppIPickDisplayMode
  168.  * Pick a display mode of one of the given depths.  640x480x16 is prefered.
  169.  */
  170. BOOL
  171. D3DAppIPickDisplayMode(int *mode, DWORD depths)
  172. {
  173.     int i, j;
  174.     for (i = 0; i < d3dappi.NumModes; i++)
  175.     if (D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths)
  176.         break;
  177.     j = i;
  178.     for (; i < d3dappi.NumModes; i++) {
  179.     if (!(D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp) & depths))
  180.         continue;
  181.     if (d3dappi.Mode[i].w == 640 && d3dappi.Mode[i].h == 480 &&
  182.         d3dappi.Mode[i].bpp == 16) {
  183.         j = i;
  184.         break;
  185.     }
  186.     }
  187.     if (j >= d3dappi.NumModes)
  188.     *mode = D3DAPP_BOGUS;
  189.     else
  190.     *mode = j;
  191.     return TRUE;
  192. }
  193.  
  194. /*
  195.  * D3DAppIVerifyDriverAndMode
  196.  * Verifies the selected driver and mode combination.  If the driver is
  197.  * specified, the mode will be changed to accomodate the driver if it's not
  198.  * compatible.  If the driver is not specified, one will be selected which is
  199.  * compatible with the specified mode.  If neither are specified, a suitable
  200.  * pair will be returned.
  201.  */
  202. BOOL
  203. D3DAppIVerifyDriverAndMode(int* lpdriver, int* lpmode)
  204. {
  205.     DWORD depths;
  206.     int driver, mode, i;
  207.     driver = *lpdriver; mode = *lpmode;
  208.  
  209.     if (mode == D3DAPP_USEWINDOW && !d3dappi.bIsPrimary) {
  210.     D3DAppISetErrorString("Cannot render to a window when the DirectDraw device is not the primary.\n");
  211.     goto exit_with_error;
  212.     }
  213.  
  214.     /*
  215.      * If I've been ask to choose a driver, choose one which is compatible
  216.      * with the specified mode.
  217.      */
  218.     if (driver == D3DAPP_YOUDECIDE) {    
  219.     if (mode == D3DAPP_USEWINDOW) {
  220.         /*
  221.          * I must find a driver for this display depth
  222.          */
  223.         depths = D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp);
  224.         ATTEMPT(D3DAppIPickDriver(&driver, depths));
  225.         if (driver == D3DAPP_BOGUS) {
  226.         D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the current display depth.\n");
  227.         goto exit_with_error;
  228.         }
  229.         /*
  230.          * I don't need to go through the mode selection since I've
  231.          * verified it here
  232.          */
  233.         goto ret_ok;
  234.     } else if (mode == D3DAPP_YOUDECIDE) {
  235.         /*
  236.          * I'm free to choose any driver which can use even one
  237.          * supported depth
  238.          */
  239.         if (d3dappi.bIsPrimary)
  240.         depths = D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp);
  241.         else
  242.         depths = 0;
  243.         for (i = 0; i < d3dappi.NumModes; i++)
  244.         depths |= D3DAppIBPPToDDBD(d3dappi.Mode[i].bpp);
  245.         ATTEMPT(D3DAppIPickDriver(&driver, depths));
  246.         if (driver == D3DAPP_BOGUS) {
  247.         D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the current display depth or any supported fullscreen mode.\n");
  248.         goto exit_with_error;
  249.         }
  250.         /*
  251.          * The mode will be chosen in the next section
  252.          */
  253.     } else {
  254.         /*
  255.          * Must pick a driver which uses the given mode depth
  256.          */
  257.         ATTEMPT(D3DAppIPickDriver(&driver,
  258.                   D3DAppIBPPToDDBD(d3dappi.Mode[mode].bpp)));
  259.         if (driver == D3DAPP_BOGUS) {
  260.         D3DAppISetErrorString("Cannot find a D3D device driver which is compatible with the specified fullscreen mode.\n");
  261.         goto exit_with_error;
  262.         }
  263.         /*
  264.          * I don't need to go through the mode selection since I've
  265.          * verified it here
  266.          */
  267.         goto ret_ok;
  268.     }
  269.     }
  270.  
  271.     /* 
  272.      * At this stage, I have a driver I want to match the mode to.
  273.      */
  274.     if (mode == D3DAPP_YOUDECIDE) {
  275.     /*
  276.      * If it's my choice, I prefer windowed over fullscreen
  277.      */
  278.     if (d3dappi.bIsPrimary) {
  279.         if (D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp) & 
  280.             d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth) {
  281.         mode = D3DAPP_USEWINDOW;
  282.         goto ret_ok;
  283.         }
  284.     }
  285.     /*
  286.      * Either this is not a primary DD device or the driver cannot use
  287.      * the Windows display depth
  288.      */
  289.     ATTEMPT(D3DAppIPickDisplayMode(&mode,
  290.             d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth));
  291.     if (mode == D3DAPP_BOGUS) {
  292.         D3DAppISetErrorString("The selected D3D device driver is not compatible with the current display depth or any supported fullscreen modes.\n");
  293.         goto exit_with_error;
  294.     }
  295.     goto ret_ok;
  296.     } else if (mode == D3DAPP_USEWINDOW) {
  297.     /*
  298.      * Check to see if this driver can use the Windows display depth
  299.      */
  300.     if (D3DAppIBPPToDDBD(d3dappi.WindowsDisplay.bpp) &
  301.         d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth) {
  302.         goto ret_ok;
  303.     } else {
  304.         /*
  305.          * Since it cannot, call this function again to choose any 
  306.          * display mode which is compatible 
  307.          */
  308.         mode = D3DAPP_YOUDECIDE;
  309.         ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode));
  310.         if (driver == D3DAPP_BOGUS)
  311.         goto exit_with_error;
  312.         goto ret_ok;
  313.     }
  314.     } else {
  315.     /*
  316.      * Check to see if this driver can use the specified fullscreen mode
  317.      */
  318.     if (D3DAppIBPPToDDBD(d3dappi.Mode[mode].bpp) &
  319.         d3dappi.Driver[driver].Desc.dwDeviceRenderBitDepth) {
  320.         goto ret_ok;
  321.     } else {
  322.         /*
  323.          * Since it cannot, call this function again to choose any
  324.          * display mode which is compatible
  325.          */
  326.         mode = D3DAPP_YOUDECIDE;
  327.         ATTEMPT(D3DAppIVerifyDriverAndMode(&driver, &mode));
  328.         if (driver == D3DAPP_BOGUS)
  329.         goto exit_with_error;
  330.         goto ret_ok;
  331.     }
  332.     }
  333.  
  334. ret_ok:
  335.     *lpdriver = driver; *lpmode = mode;
  336.     return TRUE;
  337. exit_with_error:
  338.     return FALSE;
  339. }
  340.  
  341. /***************************************************************************/
  342. /*                        Dirty Rectangle Functions                        */
  343. /***************************************************************************/
  344. /*
  345.  * D3DAppIValidateDirtyRects
  346.  * Set the dirty rectangles for the front and back buffers to the entire
  347.  * client size.
  348.  */
  349. void
  350. D3DAppIValidateDirtyRects(void)
  351. {
  352.     NumDirtyClientRects = 1; NumDirtyBackRects = 1; NumDirtyZRects = 1;
  353.     SetRect((LPRECT)&DirtyClient[0], 0, 0, d3dappi.szClient.cx,
  354.         d3dappi.szClient.cy);
  355.     SetRect((LPRECT)&DirtyBack[0], 0, 0, d3dappi.szClient.cx,
  356.         d3dappi.szClient.cy);
  357.     SetRect((LPRECT)&DirtyZ[0], 0, 0, d3dappi.szClient.cx,
  358.         d3dappi.szClient.cy);
  359. }
  360.  
  361. /*
  362.  * D3DAppICopyRectList
  363.  * Copy a list of rectangles to another
  364.  */
  365. void
  366. D3DAppICopyRectList(int* dstnum, LPD3DRECT dst, int srcnum, LPD3DRECT src)
  367. {
  368.     int i;
  369.     for (i = 0; i < srcnum; i++)
  370.     dst[i] = src[i];
  371.     *dstnum = srcnum;
  372. }
  373.  
  374. /*
  375.  * MERGE macro
  376.  * Set first rectangle to be the smallest rectangle containing both rects
  377.  */
  378. #undef MERGE
  379. #define MERGE(rc1, rc2)                \
  380.     do {                    \
  381.     if (rc2.x1 < rc1.x1) rc1.x1 = rc2.x1;    \
  382.     if (rc2.y1 < rc1.y1) rc1.y1 = rc2.y1;    \
  383.     if (rc2.x2 > rc1.x2) rc1.x2 = rc2.x2;    \
  384.     if (rc2.y2 > rc1.y2) rc1.y2 = rc2.y2;    \
  385.     } while(0)
  386.  
  387. /*
  388.  * D3DAppIMergeRectLists
  389.  * Merge two lists of rectangles to create another list of rectangles. The
  390.  * merged list of rectangles covers all the area of the original two with NO
  391.  * OVERLAPPING amongst it's rectangles.
  392.  */
  393. void
  394. D3DAppIMergeRectLists(int* dstnum, LPD3DRECT dst, int src1num, LPD3DRECT src1,
  395.              int src2num, LPD3DRECT src2)
  396. {
  397.     LPD3DRECT rc;
  398.     int* isvalid;
  399.     int num, i, j, intersect;
  400.     rc = (LPD3DRECT)malloc(sizeof(D3DRECT) * D3DAPP_MAXCLEARRECTS * 2);
  401.     memset(rc, 0, sizeof(D3DRECT) * D3DAPP_MAXCLEARRECTS * 2);
  402.     isvalid = (int*)malloc(sizeof(int) * D3DAPP_MAXCLEARRECTS * 2);
  403.     memset(isvalid, 0, sizeof(int) * D3DAPP_MAXCLEARRECTS * 2);
  404.     for (i = 0; i < src1num; i++) {
  405.     memcpy(&rc[i], &src1[i], sizeof(D3DRECT));
  406.     if ((rc[i].x1 == 0 && rc[i].x2 == 0) ||
  407.         (rc[i].y1 == 0 && rc[i].y2 == 0))
  408.         isvalid[i] = 0;
  409.         else if (rc[i].x1 <= rc[i].x2 && rc[i].y1 <= rc[i].y2)
  410.         isvalid[i] = 1;
  411.         else
  412.             isvalid[i] = 0;
  413.     }
  414.     for (i = 0; i < src2num; i++) {
  415.     memcpy(&rc[i + src1num], &src2[i], sizeof(D3DRECT));
  416.         if (rc[i + src1num].x1 <= rc[i + src1num].x2 &&
  417.             rc[i + src1num].y1 <= rc[i + src1num].y2)
  418.         isvalid[i + src1num] = 1;
  419.         else
  420.             isvalid[i + src1num] = 0;
  421.  
  422.     }
  423.     num = src1num + src2num;
  424.     for (i = 0; i < num - 1; i++) {
  425.         if (!isvalid[i]) continue;
  426.     j = i + 1;
  427.     do {
  428.         intersect = 0;
  429.         for (; j < num; j++) {
  430.         if (j != i && isvalid[j]) {
  431.             if (rc[i].x1 < rc[j].x1) {
  432.             if (rc[i].x2 < rc[j].x1)
  433.                 continue;
  434.             } else {
  435.             if (rc[j].x2 < rc[i].x1)
  436.                 continue;
  437.             }
  438.             if (rc[i].y1 < rc[j].y1) {
  439.             if (rc[i].y2 < rc[j].y1)
  440.                 continue;
  441.             } else {
  442.             if (rc[j].y2 < rc[i].y1)
  443.                 continue;
  444.             }
  445.             MERGE(rc[i], rc[j]);
  446.             isvalid[j] = 0;
  447.             j = 0; intersect = 1;
  448.             break;
  449.         }
  450.         }
  451.     } while(intersect);
  452.     }
  453.  
  454.     for (i = 0, j = 0; i < num; i++)
  455.     if (isvalid[i]) ++j;
  456.     if (j > D3DAPP_MAXCLEARRECTS) {
  457.     for (i = 0; i < num; i++)
  458.         if (isvalid[i]) break;
  459.     if (i < num) {
  460.         *dstnum = 1;
  461.         dst[0] = rc[i];
  462.         for (; i < num; i++) {
  463.         if (isvalid[i]) {
  464.             MERGE(dst[0], rc[i]);
  465.         }
  466.         }
  467.     } else {
  468.         *dstnum = 0;
  469.     }
  470.     } else {
  471.     for (i = 0, j = 0; i < num; i++) {
  472.         if (isvalid[i]) {
  473.         memcpy(&dst[j], &rc[i], sizeof(D3DRECT));
  474.         ++j;
  475.         }
  476.     }
  477.     *dstnum = j;
  478.     }
  479.     free(rc);
  480.     free(isvalid);
  481. }
  482.  
  483. /***************************************************************************/
  484. /*                     Getting and Setting Window Attribs                  */
  485. /***************************************************************************/
  486. /*
  487.  * D3DAppISetClientSize
  488.  * Set the client size of the given window.  A WM_SIZE message is generated,
  489.  * but ignored.
  490.  */
  491. void
  492. D3DAppISetClientSize(HWND hwnd, int w, int h, BOOL bReturnFromFullscreen)
  493. {
  494.     RECT rc;
  495.  
  496.     bIgnoreWM_SIZE = TRUE;
  497.     if (bReturnFromFullscreen) {
  498.     SetRect(&rc, 0, 0, w, h);
  499.     AdjustWindowRectEx(&rc, GetWindowLong(hwnd, GWL_STYLE),
  500.                    GetMenu(hwnd) != NULL,
  501.                    GetWindowLong(hwnd, GWL_EXSTYLE));
  502.     SetWindowPos(hwnd, NULL, 0, 0, rc.right-rc.left,
  503.                  rc.bottom-rc.top,
  504.                  SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  505.     SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
  506.                  SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  507.  
  508.     } else {
  509.     /*
  510.      * This is the only way to set the client size correctly if the menu
  511.      * is stacked, so do it unless we are returning from a fullscreen
  512.      * mode.
  513.      */
  514.     SendMessage(hwnd, WM_SIZE, SIZE_RESTORED, w + h << 16);
  515.     GetWindowRect(hwnd, &rc);
  516.     SetWindowPos(hwnd, NULL, 0, 0, rc.right-rc.left,
  517.                  rc.bottom-rc.top,
  518.                  SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  519.     SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
  520.                  SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  521.     }
  522.     bIgnoreWM_SIZE = FALSE;
  523.     d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0;
  524.     ClientToScreen(hwnd, &d3dappi.pClientOnPrimary);
  525.     d3dappi.szClient.cx = w; d3dappi.szClient.cy = h;
  526. }
  527.  
  528. /*
  529.  * D3DAppIGetClientWin
  530.  * Gets the client window size and sets it in the D3DAppInfo structure
  531.  */
  532. void
  533. D3DAppIGetClientWin(HWND hwnd)
  534. {
  535.     RECT rc;
  536.     if (!d3dappi.bFullscreen) {
  537.     d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0;
  538.     ClientToScreen(hwnd, &d3dappi.pClientOnPrimary);
  539.     GetClientRect(hwnd, &rc);
  540.     d3dappi.szClient.cx = rc.right;
  541.     d3dappi.szClient.cy = rc.bottom;
  542.     } else {
  543.     /*
  544.      * In the fullscreen case, we must be careful because if the window
  545.      * frame has been drawn, the client size has shrunk and this can
  546.      * cause problems, so it's best to report the entire screen.
  547.      */
  548.     d3dappi.pClientOnPrimary.x = d3dappi.pClientOnPrimary.y = 0;
  549.     d3dappi.szClient.cx = d3dappi.ThisMode.w;
  550.     d3dappi.szClient.cy = d3dappi.ThisMode.h;
  551.     }
  552. }
  553.  
  554.  
  555. /***************************************************************************/
  556. /*                              Error reporting                            */
  557. /***************************************************************************/
  558.  
  559. /*
  560.  * D3DAppISetErrorString
  561.  * Set the global variable which records the last error string.
  562.  */
  563. void
  564. D3DAppISetErrorString( LPSTR fmt, ... )
  565. {
  566.     char buff[256];
  567.     va_list args;
  568.     
  569.     buff[0] = 0;
  570.     va_start(args, fmt);
  571.     wvsprintf(&buff[0], fmt, args);
  572.     va_end(args);
  573.     
  574.     lstrcat(buff, "\r\n");
  575.     lstrcpy(LastErrorString, buff);
  576. }
  577.  
  578. /* dpf
  579.  * Debug printf.  Very useful for fullscreen exclusive mode or when surfaces
  580.  * are in video memory.
  581.  */
  582. void __cdecl
  583. dpf( LPSTR fmt, ... )
  584. {
  585.     char buff[256];
  586.     va_list args;
  587.     
  588.     lstrcpy(buff, "D3DApp: ");
  589.     va_start(args, fmt);
  590.     wvsprintf(&buff[lstrlen(buff)], fmt, args);
  591.     va_end(args);
  592.     
  593.     lstrcat(buff, "\r\n");
  594.     OutputDebugString(buff);
  595. }
  596.