home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / FOXBEAR / DDRAW.C < prev    next >
C/C++ Source or Header  |  1996-08-28  |  23KB  |  845 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4.  *  Copyright (C) 1994-1995 ATI Technologies Inc. All Rights Reserved.
  5.  *
  6.  *  File:       ddraw.c
  7.  *  Content:    Misc. Direct Draw access routines
  8.  *
  9.  ***************************************************************************/
  10. #include "foxbear.h"
  11.  
  12. BOOL    bUseEmulation;
  13. BOOL    bUseSysMem;
  14. int     nBufferCount;
  15. int     CmdLineBufferCount;
  16. BOOL    bTransDest;
  17. BOOL    bColorFill;
  18.  
  19. HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context);
  20.  
  21. /*
  22.  * DDEnable
  23.  */
  24. BOOL DDEnable( void )
  25. {
  26.     LPDIRECTDRAW        lpdd;
  27.     DDCAPS              ddcaps;
  28.     HRESULT             ddrval;
  29.     BOOL                use_dest;
  30.  
  31.     nBufferCount = GetProfileInt( "FoxBear", "buffers", CmdLineBufferCount);
  32.     bUseEmulation = GetProfileInt( "FoxBear", "use_emulation", bUseEmulation);
  33.     bUseSysMem = GetProfileInt( "FoxBear", "sysmem", 0);
  34.     use_dest = GetProfileInt( "FoxBear", "use_dest", 0 );
  35.  
  36.     if (lpDD == NULL)
  37.     {
  38.         if( bUseEmulation )
  39.         {
  40.             ddrval = DirectDrawCreate( (LPVOID) DDCREATE_EMULATIONONLY, &lpdd, NULL );
  41.         }
  42.         else
  43.         {
  44.             ddrval = DirectDrawCreate( NULL, &lpdd, NULL );
  45.         }
  46.     }
  47.     else
  48.     {
  49.         lpdd = lpDD;
  50.         ddrval = DD_OK;
  51.     }
  52.  
  53.     if( ddrval != DD_OK )
  54.     {
  55.         Msg("DirectDrawCreate failed err=%d", ddrval);
  56.         goto error;
  57.     }
  58.  
  59.     /*
  60.      * grab exclusive mode if we are going to run as fullscreen
  61.      * otherwise grab normal mode.
  62.      */
  63.     if (lpDD == NULL)
  64.     {
  65.         NumModes = 0;
  66.  
  67.         if (bFullscreen)
  68.         {
  69.             ddrval = IDirectDraw_SetCooperativeLevel( lpdd, hWndMain,
  70.                             DDSCL_ALLOWMODEX |
  71.                             DDSCL_EXCLUSIVE |
  72.                             DDSCL_FULLSCREEN );
  73.  
  74.             // in fullscreen mode, enumeratte the available modes
  75.             IDirectDraw_EnumDisplayModes(lpdd, 0, NULL, 0, EnumDisplayModesCallback);
  76.         }
  77.         else
  78.         {
  79.             ddrval = IDirectDraw_SetCooperativeLevel( lpdd, hWndMain,
  80.                             DDSCL_NORMAL );
  81.  
  82.             // in normal windowed mode, just add some "stock" window
  83.             // sizes
  84.  
  85.             ModeList[NumModes].w = 320;
  86.             ModeList[NumModes].h = 200;
  87.             NumModes++;
  88.  
  89.             ModeList[NumModes].w = 320;
  90.             ModeList[NumModes].h = 240;
  91.             NumModes++;
  92.  
  93.             ModeList[NumModes].w = 512;
  94.             ModeList[NumModes].h = 384;
  95.             NumModes++;
  96.  
  97.             ModeList[NumModes].w = 640;
  98.             ModeList[NumModes].h = 400;
  99.             NumModes++;
  100.  
  101.             ModeList[NumModes].w = 640;
  102.             ModeList[NumModes].h = 480;
  103.             NumModes++;
  104.         }
  105.  
  106.         if( ddrval != DD_OK )
  107.         {
  108.             Msg("SetCooperativeLevel failed err=%d", ddrval);
  109.             goto error;
  110.         }
  111.     }
  112.  
  113.     if (bFullscreen)
  114.     {
  115.         Msg("SetDisplayMode %d %d %d",GameMode.cx,GameMode.cy, GameBPP);
  116.         ddrval = IDirectDraw_SetDisplayMode( lpdd,
  117.             GameMode.cx, GameMode.cy, GameBPP);
  118.  
  119.         if (ddrval != DD_OK && (GameMode.cx != 640 || GameMode.cy != 480))
  120.         {
  121.             Msg( "cant set mode trying 640x480" );
  122.  
  123.             GameMode.cx = 640;
  124.             GameMode.cy = 480;
  125.             GameSize = GameMode;
  126.  
  127.             ddrval = IDirectDraw_SetDisplayMode( lpdd,
  128.                 GameMode.cx, GameMode.cy, GameBPP);
  129.         }
  130.  
  131.         if (ddrval != DD_OK && GameBPP != 8)
  132.         {
  133.             Msg( "cant set mode trying 640x480x8" );
  134.  
  135.             GameBPP = 8;
  136.  
  137.             ddrval = IDirectDraw_SetDisplayMode( lpdd,
  138.                 GameMode.cx, GameMode.cy, GameBPP);
  139.         }
  140.  
  141.         if (ddrval != DD_OK && GameBPP != 16)
  142.         {
  143.             Msg( "cant set mode trying 640x480x16" );
  144.  
  145.             GameBPP = 16;
  146.  
  147.             ddrval = IDirectDraw_SetDisplayMode( lpdd,
  148.                 GameMode.cx, GameMode.cy, GameBPP);
  149.         }
  150.  
  151.         if( ddrval != DD_OK )
  152.         {
  153.             Msg("SetMode failed err=%d", ddrval);
  154.             goto error;
  155.         }
  156.     }
  157.     else
  158.     {
  159.         RECT rcWork;
  160.         RECT rc;
  161.         HDC hdc;
  162.         DWORD dwStyle;
  163.  
  164.         //
  165.         //  when in rome (I mean when in windows) we should use the
  166.         //  current mode
  167.         //
  168.         hdc = GetDC(NULL);
  169.         GameBPP = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
  170.         ReleaseDC(NULL, hdc);
  171.  
  172.         //
  173.         // if we are still a WS_POPUP window we should convert to a
  174.         // normal app window so we look like a windows app.
  175.         //
  176.         dwStyle = GetWindowStyle(hWndMain);
  177.         dwStyle &= ~WS_POPUP;
  178.         dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
  179.         SetWindowLong(hWndMain, GWL_STYLE, dwStyle);
  180.  
  181.         if (bStretch)
  182.             SetRect(&rc, 0, 0, GameMode.cx*2, GameMode.cy*2);
  183.         else
  184.             SetRect(&rc, 0, 0, GameMode.cx, GameMode.cy);
  185.  
  186.         AdjustWindowRectEx(&rc,
  187.             GetWindowStyle(hWndMain),
  188.             GetMenu(hWndMain) != NULL,
  189.             GetWindowExStyle(hWndMain));
  190.  
  191.         SetWindowPos(hWndMain, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
  192.             SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  193.  
  194.         SetWindowPos(hWndMain, HWND_NOTOPMOST, 0, 0, 0, 0,
  195.             SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  196.  
  197.         //
  198.         //  make sure our window does not hang outside of the work area
  199.         //  this will make people who have the tray on the top or left
  200.         //  happy.
  201.         //
  202.         SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
  203.         GetWindowRect(hWndMain, &rc);
  204.         if (rc.left < rcWork.left) rc.left = rcWork.left;
  205.         if (rc.top  < rcWork.top)  rc.top  = rcWork.top;
  206.         SetWindowPos(hWndMain, NULL, rc.left, rc.top, 0, 0,
  207.             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  208.     }
  209.  
  210.     /*
  211.      * check capabilites
  212.      */
  213.     ddcaps.dwSize = sizeof( ddcaps );
  214.     ddrval = IDirectDraw_GetCaps( lpdd, &ddcaps, NULL );
  215.  
  216.     if( ddrval != DD_OK )
  217.     {
  218.         Msg("GetCaps failed err=%d", ddrval);
  219.         goto error;
  220.     }
  221.  
  222.     if( ddcaps.dwCaps & DDCAPS_NOHARDWARE )
  223.     {
  224.         Msg( "No hardware support at all" );
  225.     }
  226.  
  227.     if( ddcaps.dwCaps & DDCAPS_BLTCOLORFILL )
  228.     {
  229.         bColorFill = TRUE;
  230.         Msg( "Device supports color fill" );
  231.     }
  232.     else
  233.     {
  234.         bColorFill = FALSE;
  235.         Msg( "Device does not support color fill" );
  236.     }
  237.  
  238.     /*
  239.      * default to double buffered on 1mb, triple buffered
  240.      * on > 1mb
  241.      */
  242.     if (nBufferCount == 0)
  243.     {
  244.         if( ddcaps.dwVidMemTotal <= 1024L*1024L*(GameBPP/8) ||
  245.             GameMode.cx > 640 )
  246.         {
  247.             Msg("double buffering (not enough memory)");
  248.             nBufferCount = 2;
  249.         }
  250.         else
  251.         {
  252.             Msg("triple buffering");
  253.             nBufferCount = 3;
  254.         }
  255.     }
  256.  
  257.     if( ddcaps.dwCaps & DDCAPS_COLORKEY )
  258.     {
  259.         if( ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT )
  260.         {
  261.             Msg( "Can do Src colorkey in hardware" );
  262.         }
  263.  
  264.         if( ddcaps.dwCKeyCaps & DDCKEYCAPS_DESTBLT )
  265.         {
  266.             Msg( "Can do Dest colorkey in hardware" );
  267.             if( use_dest || !(ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) )
  268.             {
  269.                 /*
  270.                  * since direct draw doesn't support
  271.                  * destination color key in emulation, only
  272.                  * use it if there is enough vram ...
  273.                  */
  274.                 if( ddcaps.dwVidMemTotal >= 2 * 1024L*1024L*(GameBPP/8) )
  275.                 {
  276.                     Msg( "Using destination color key" );
  277.                     bTransDest = TRUE;
  278.                 }
  279.             }
  280.         }
  281.     }
  282.     else
  283.     {
  284.         Msg( "Can't do color key in hardware!" );
  285.     }
  286.  
  287.     lpDD = lpdd;
  288.     return TRUE;
  289.  
  290. error:
  291.     return FALSE;
  292.  
  293. } /* DDEnable */
  294.  
  295. /*
  296.  * DDDisable
  297.  */
  298. BOOL DDDisable( BOOL fFinal )
  299. {
  300.     if( lpClipper )
  301.     {
  302.         IDirectDrawClipper_Release(lpClipper);
  303.         lpClipper = NULL;
  304.     }
  305.  
  306.     if( lpBackBuffer )
  307.     {
  308.         IDirectDrawSurface_Release(lpBackBuffer);
  309.         lpBackBuffer = NULL;
  310.     }
  311.  
  312.     if( lpFrontBuffer )
  313.     {
  314.         IDirectDrawSurface_Release(lpFrontBuffer);
  315.         lpFrontBuffer = NULL;
  316.     }
  317.  
  318.     if( lpStretchBuffer )
  319.     {
  320.         IDirectDrawSurface_Release(lpStretchBuffer);
  321.         lpStretchBuffer = NULL;
  322.     }
  323.  
  324.     //
  325.     // fFinal is TRUE when the app is exiting, FALSE if we are
  326.     // just seting a new game size..
  327.     //
  328.     if ( fFinal )
  329.     {
  330.         if( lpDD != NULL )
  331.         {
  332.             IDirectDraw_Release( lpDD );
  333.             lpDD = NULL;
  334.         }
  335.     }
  336.  
  337.     return TRUE;
  338. }
  339.  
  340. /*
  341.  * DDClear
  342.  *
  343.  * clear the front buffer and all backbuffers.
  344.  */
  345. BOOL DDClear( void )
  346. {
  347.     DDBLTFX     ddbltfx;
  348.     int         i;
  349.     HRESULT     ddrval;
  350.  
  351.     UpdateWindow(hWndMain);
  352.  
  353.     ddbltfx.dwSize = sizeof( ddbltfx );
  354.     ddbltfx.dwFillColor = DDColorMatch(lpBackBuffer, RGB(0, 0, 200));
  355.  
  356.     if (bFullscreen)
  357.     {
  358.         /*
  359.          * do it for all buffers, we either have 1 or 2 back buffers
  360.          * make sure we get them all, 4 is plenty!
  361.          */
  362.         for( i=0; i<4; i++ )
  363.         {
  364.             ddrval = IDirectDrawSurface_Blt(
  365.                             lpBackBuffer,           // dest surface
  366.                             NULL,                   // dest rect
  367.                             NULL,                   // src surface
  368.                             NULL,                   // src rect
  369.                             DDBLT_COLORFILL | DDBLT_WAIT,
  370.                             &ddbltfx);
  371.  
  372.             if( ddrval != DD_OK )
  373.             {
  374.                 Msg("Fill failed ddrval =0x%08lX", ddrval);
  375.                 return FALSE;
  376.             }
  377.  
  378.             ddrval = IDirectDrawSurface_Flip(lpFrontBuffer, NULL, DDFLIP_WAIT);
  379.  
  380.             if( ddrval != DD_OK )
  381.             {
  382.                 Msg("Flip failed ddrval =0x%08lX", ddrval );
  383.                 return FALSE;
  384.             }
  385.         }
  386.     }
  387.     else
  388.     {
  389.         ddrval = IDirectDrawSurface_Blt(
  390.                         lpFrontBuffer,          // dest surface
  391.                         &rcWindow,              // dest rect
  392.                         NULL,                   // src surface
  393.                         NULL,                   // src rect
  394.                         DDBLT_COLORFILL | DDBLT_WAIT,
  395.                         &ddbltfx);
  396.  
  397.         if( ddrval != DD_OK )
  398.         {
  399.             Msg("Fill failed ddrval =0x%08lX", ddrval);
  400.             return FALSE;
  401.         }
  402.     }
  403.  
  404.     return TRUE;
  405.  
  406. } /* DDClear */
  407.  
  408. /*
  409.  * DDCreateFlippingSurface
  410.  *
  411.  * create a FrontBuffer and a BackBuffer(s)
  412.  *
  413.  */
  414. BOOL DDCreateFlippingSurface( void )
  415. {
  416.     DDPIXELFORMAT       ddpf;
  417.     DDSURFACEDESC       ddsd;
  418.     HRESULT             ddrval;
  419.     DDSCAPS             ddscaps;
  420.     DDCAPS              ddcaps;
  421.  
  422.     ddcaps.dwSize = sizeof( ddcaps );
  423.  
  424.     if( IDirectDraw_GetCaps( lpDD, &ddcaps, NULL ) != DD_OK )
  425.         return FALSE;
  426.  
  427.     /*
  428.      * fill in surface desc:
  429.      * want a primary surface with 2 back buffers
  430.      */
  431.     ZeroMemory( &ddsd, sizeof( ddsd ) );
  432.     ddsd.dwSize = sizeof( ddsd );
  433.  
  434.     if (bFullscreen && nBufferCount > 1)
  435.     {
  436.         //
  437.         //  fullscreen case, create a primary (ie front) and
  438.         //  either 1  or 2 back buffers
  439.         //
  440.         ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  441.         ddsd.dwBackBufferCount = nBufferCount-1;
  442.         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
  443.                 DDSCAPS_FLIP | DDSCAPS_COMPLEX;
  444.  
  445.         OutputDebugString("Creating multiple backbuffer primary\n\r");
  446.         ddrval = IDirectDraw_CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
  447.  
  448.         if( ddrval != DD_OK )
  449.         {
  450.             Msg( "CreateSurface FAILED! %08lx", ddrval );
  451.             return FALSE;
  452.         }
  453.  
  454.         /*
  455.          * go find the back buffer
  456.          */
  457.         ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  458.         ddrval = IDirectDrawSurface_GetAttachedSurface(
  459.                     lpFrontBuffer,
  460.                     &ddscaps,
  461.                     &lpBackBuffer );
  462.  
  463.         if( ddrval != DD_OK )
  464.         {
  465.             Msg( "GetAttachedSurface failed! err=%d",ddrval );
  466.             return FALSE;
  467.         }
  468.  
  469.         /*
  470.          *  if we are stretching create a buffer to stretch into
  471.          *
  472.          *  NOTE we always make this buffer in system memory because
  473.          *  we render to the backbuffer (in VRAM) at half the size
  474.          *  now we need to stretch into the backbuffer.  we could just
  475.          *  do a VRAM->VRAM stretch, but this is REAL REAL REAL slow on
  476.          *  some cards (banked cards..)
  477.          */
  478.         if( bStretch && (ddcaps.dwCaps & DDCAPS_BANKSWITCHED) )
  479.         {
  480.             Msg( "On bank switched hardware, creating stretch buffer" );
  481.             lpStretchBuffer = DDCreateSurface( GameSize.cx, GameSize.cy,
  482.                                                 TRUE, FALSE );
  483.         }
  484.     }
  485.     else if (bFullscreen && nBufferCount == 1)
  486.     {
  487.         ddsd.dwFlags = DDSD_CAPS;
  488.         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  489.  
  490.         OutputDebugString("Creating no backbuffer primary\n\r");
  491.         ddrval = IDirectDraw_CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
  492.  
  493.         if( ddrval != DD_OK )
  494.         {
  495.             Msg( "CreateSurface FAILED! %08lx", ddrval );
  496.             return FALSE;
  497.         }
  498.  
  499.         IDirectDrawSurface_AddRef(lpFrontBuffer);
  500.         lpBackBuffer = lpFrontBuffer;
  501.     }
  502.     else
  503.     {
  504.         //
  505.         //  window case, create the primary surface
  506.         //  and create a backbuffer in offscreen memory.
  507.         //
  508.         ddsd.dwFlags = DDSD_CAPS;
  509.         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  510.  
  511.         ddrval = IDirectDraw_CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
  512.  
  513.         if( ddrval != DD_OK )
  514.         {
  515.             Msg( "CreateSurface FAILED! %08lx", ddrval );
  516.             return FALSE;
  517.         }
  518.  
  519.         lpBackBuffer = DDCreateSurface( GameSize.cx, GameSize.cy, FALSE, FALSE );
  520.  
  521.         if( lpBackBuffer == NULL )
  522.         {
  523.             Msg( "Cant create the backbuffer" );
  524.             return FALSE;
  525.         }
  526.  
  527.         //
  528.         // now create a DirectDrawClipper object.
  529.         //
  530.         ddrval = IDirectDraw_CreateClipper(lpDD, 0, &lpClipper, NULL);
  531.  
  532.         if( ddrval != DD_OK )
  533.         {
  534.             Msg("Cant create clipper");
  535.             return FALSE;
  536.         }
  537.  
  538.         ddrval = IDirectDrawClipper_SetHWnd(lpClipper, 0, hWndMain);
  539.  
  540.         if( ddrval != DD_OK )
  541.         {
  542.             Msg("Cant set clipper window handle");
  543.             return FALSE;
  544.         }
  545.  
  546.         ddrval = IDirectDrawSurface_SetClipper(lpFrontBuffer, lpClipper);
  547.  
  548.         if( ddrval != DD_OK )
  549.         {
  550.             Msg("Cant attach clipper to front buffer");
  551.             return FALSE;
  552.         }
  553.     }
  554.  
  555.     /*
  556.      * init the color key
  557.      */
  558.     ddpf.dwSize = sizeof(ddpf);
  559.     IDirectDrawSurface_GetPixelFormat(lpFrontBuffer, &ddpf);
  560.  
  561.     /*
  562.      * we use white as the color key, if we are in a 8bpp mode, we know
  563.      * what white is (because we use a 332 palette) if we are not in a
  564.      * a 8bpp mode we dont know what white is and we need to figure it
  565.      * out from the device (remember 16bpp comes in two common flavors
  566.      * 555 and 565).  if we wanted to any random color as the color key
  567.      * we would call DDColorMatch (see below) to convert a RGB into a
  568.      * physical color.
  569.      */
  570.     if (ddpf.dwRGBBitCount == 8)
  571.         dwColorKey = 0xff;
  572.     else
  573.         dwColorKey = ddpf.dwRBitMask | ddpf.dwGBitMask | ddpf.dwBBitMask;
  574.  
  575.     Msg("dwColorKey = 0x%08lX", dwColorKey);
  576.  
  577.     if( bTransDest )
  578.     {
  579.         DDCOLORKEY              ddck;
  580.         ddck.dwColorSpaceLowValue = dwColorKey;
  581.         ddck.dwColorSpaceHighValue = dwColorKey;
  582.         IDirectDrawSurface_SetColorKey( lpBackBuffer, DDCKEY_DESTBLT, &ddck);
  583.     }
  584.  
  585.     return TRUE;
  586.  
  587. } /* DDCreateFlippingSurface */
  588.  
  589. /*
  590.  * DDCreateSurface
  591.  */
  592. LPDIRECTDRAWSURFACE DDCreateSurface(
  593.                 DWORD width,
  594.                 DWORD height,
  595.                 BOOL sysmem,
  596.                 BOOL trans )
  597. {
  598.     DDSURFACEDESC       ddsd;
  599.     HRESULT             ddrval;
  600.     DDCOLORKEY          ddck;
  601.     LPDIRECTDRAWSURFACE psurf;
  602.  
  603.  
  604.     /*
  605.      * fill in surface desc
  606.      */
  607.     memset( &ddsd, 0, sizeof( ddsd ) );
  608.     ddsd.dwSize = sizeof( ddsd );
  609.     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
  610.  
  611.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  612.     if( sysmem || bUseSysMem )
  613.     {
  614.         ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  615.     }
  616.  
  617.     ddsd.dwHeight = height;
  618.     ddsd.dwWidth = width;
  619.  
  620.     ddrval = IDirectDraw_CreateSurface( lpDD, &ddsd, &psurf, NULL );
  621.  
  622.     /*
  623.      * set the color key for this bitmap
  624.      */
  625.     if( ddrval == DD_OK )
  626.     {
  627.         if( trans && !bTransDest )
  628.         {
  629.             ddck.dwColorSpaceLowValue = dwColorKey;
  630.             ddck.dwColorSpaceHighValue = dwColorKey;
  631.             IDirectDrawSurface_SetColorKey( psurf, DDCKEY_SRCBLT, &ddck);
  632.         }
  633.     }
  634.     else
  635.     {
  636.         Msg( "CreateSurface FAILED, rc = %ld", (DWORD) LOWORD( ddrval ) );
  637.         psurf = NULL;
  638.     }
  639.  
  640.      return psurf;
  641.  
  642. } /* DDCreateSurface */
  643.  
  644. DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb)
  645. {
  646.     COLORREF rgbT;
  647.     HDC hdc;
  648.     DWORD dw = CLR_INVALID;
  649.     DDSURFACEDESC ddsd;
  650.     HRESULT hres;
  651.  
  652.     if (IDirectDrawSurface_GetDC(pdds, &hdc) == DD_OK)
  653.     {
  654.         rgbT = GetPixel(hdc, 0, 0);
  655.         SetPixel(hdc, 0, 0, rgb);
  656.         IDirectDrawSurface_ReleaseDC(pdds, hdc);
  657.     }
  658.  
  659.     ddsd.dwSize = sizeof(ddsd);
  660.     hres = IDirectDrawSurface_Lock(
  661.         pdds, NULL, &ddsd, DDLOCK_WAIT, NULL);
  662.  
  663.     if (hres == DD_OK)
  664.     {
  665.         dw  = *(DWORD *)ddsd.lpSurface;
  666.         if(ddsd.ddpfPixelFormat.dwRGBBitCount != 32)
  667.             dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;
  668.         IDirectDrawSurface_Unlock(pdds, NULL);
  669.     }
  670.     else
  671.     {
  672.         IDirectDrawSurface_GetSurfaceDesc(pdds,&ddsd);
  673.         if(ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
  674.             Msg("Failed to lock Primary Surface!");
  675.         else
  676.             Msg("Failed to lock NON-PRIMARY Surface!");
  677.     }
  678.  
  679.     if (IDirectDrawSurface_GetDC(pdds, &hdc) == DD_OK)
  680.     {
  681.         SetPixel(hdc, 0, 0, rgbT);
  682.         IDirectDrawSurface_ReleaseDC(pdds, hdc);
  683.     }
  684.  
  685.     return dw;
  686. }
  687.  
  688. /*
  689.  * ReadPalFile
  690.  *
  691.  * Create a DirectDrawPalette from a palette file
  692.  *
  693.  * if the palette files cant be found, make a default 332 palette
  694.  */
  695. LPDIRECTDRAWPALETTE ReadPalFile( char *fname )
  696. {
  697.     int                 i;
  698.     int                 fh;
  699.     HRESULT             ddrval;
  700.     IDirectDrawPalette *ppal;
  701.  
  702.     struct  {
  703.         DWORD           dwRiff;
  704.         DWORD           dwFileSize;
  705.         DWORD           dwPal;
  706.         DWORD           dwData;
  707.         DWORD           dwDataSize;
  708.         WORD            palVersion;
  709.         WORD            palNumEntries;
  710.         PALETTEENTRY    ape[256];
  711.     }   pal;
  712.  
  713.     pal.dwRiff = 0;
  714.  
  715.     if (fname)
  716.     {
  717.         fh = _lopen( fname, OF_READ);
  718.  
  719.         if (fh != -1)
  720.         {
  721.             _lread(fh, &pal, sizeof(pal));
  722.             _lclose(fh);
  723.         }
  724.     }
  725.  
  726.     /*
  727.      * if the file is not a palette file, or does not exist
  728.      * default to a 332 palette
  729.      */
  730.     if (pal.dwRiff != 0x46464952 || // 'RIFF'
  731.         pal.dwPal  != 0x204C4150 || // 'PAL '
  732.         pal.dwData != 0x61746164 || // 'data'
  733.         pal.palVersion != 0x0300 ||
  734.         pal.palNumEntries > 256  ||
  735.         pal.palNumEntries < 1)
  736.     {
  737.         Msg("Can't open palette file, using default 332.");
  738.  
  739.         for( i=0; i<256; i++ )
  740.         {
  741.             pal.ape[i].peRed   = (BYTE)(((i >> 5) & 0x07) * 255 / 7);
  742.             pal.ape[i].peGreen = (BYTE)(((i >> 2) & 0x07) * 255 / 7);
  743.             pal.ape[i].peBlue  = (BYTE)(((i >> 0) & 0x03) * 255 / 3);
  744.             pal.ape[i].peFlags = (BYTE)0;
  745.         }
  746.     }
  747.  
  748.     ddrval = IDirectDraw_CreatePalette(
  749.                             lpDD,
  750.                             DDPCAPS_8BIT,
  751.                             pal.ape,
  752.                             &ppal,
  753.                             NULL );
  754.     return ppal;
  755.  
  756. } /* ReadPalFile */
  757.  
  758.  
  759. /*
  760.  * Splash
  761.  *
  762.  * Draw a splash screen during startup
  763.  * NOTE the screen has been cleared in DDCreateFlippingSurface
  764.  */
  765. void Splash( void )
  766. {
  767.     HDC hdc;
  768.     HRESULT err;
  769.  
  770.     DDClear();
  771.  
  772.     if ((err = IDirectDrawSurface_GetDC(lpFrontBuffer, &hdc)) == DD_OK)
  773.     {
  774.         char *szMsg = "FoxBear is loading.......please wait.";
  775.         SetTextColor(hdc, RGB(255,255,255));
  776.         SetBkMode(hdc, TRANSPARENT);
  777.         TextOut(hdc, rcWindow.left, rcWindow.top, szMsg, lstrlen(szMsg));
  778.         IDirectDrawSurface_ReleaseDC(lpFrontBuffer, hdc);
  779.     }
  780.     else
  781.     {
  782.         Msg("GetDC failed! 0x%x",err);
  783.     }
  784.  
  785. } /* Splash */
  786.  
  787. /*
  788.  * MEMORY ALLOCATION ROUTINES...
  789.  */
  790.  
  791. /*
  792.  * MemAlloc
  793.  */
  794. LPVOID MemAlloc( UINT size )
  795. {
  796.     LPVOID      ptr;
  797.  
  798.     ptr = LocalAlloc( LPTR, size );
  799.     return ptr;
  800.  
  801. } /* MemAlloc */
  802.  
  803. /*
  804.  * CMemAlloc
  805.  */
  806. LPVOID CMemAlloc( UINT cnt, UINT isize )
  807. {
  808.     DWORD       size;
  809.     LPVOID      ptr;
  810.  
  811.     size = cnt * isize;
  812.     ptr = LocalAlloc( LPTR, size );
  813.     return ptr;
  814.  
  815. } /* CMemAlloc */
  816.  
  817. /*
  818.  * MemFree
  819.  */
  820. void MemFree( LPVOID ptr )
  821. {
  822.     if( ptr != NULL )
  823.     {
  824.         LocalFree( ptr );
  825.     }
  826.  
  827. } /* MemFree */
  828.  
  829. HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context)
  830. {
  831.     Msg("Mode: %dx%dx%d", pddsd->dwWidth, pddsd->dwHeight,pddsd->ddpfPixelFormat.dwRGBBitCount);
  832.     if(
  833.         (ModeList[NumModes-1].w == (int)pddsd->dwWidth)&&
  834.         (ModeList[NumModes-1].h == (int)pddsd->dwHeight)&&
  835.         (ModeList[NumModes-1].bpp == (int)pddsd->ddpfPixelFormat.dwRGBBitCount)
  836.       )
  837.         return DDENUMRET_OK;
  838.     ModeList[NumModes].w   = pddsd->dwWidth;
  839.     ModeList[NumModes].h   = pddsd->dwHeight;
  840.     ModeList[NumModes].bpp = pddsd->ddpfPixelFormat.dwRGBBitCount;
  841.     NumModes++;
  842.  
  843.     return DDENUMRET_OK;
  844. }
  845.