GFX.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:15k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       gfx.c
  6.  *  Content:    DirectDraw related code.
  7.  *
  8.  *
  9.  ***************************************************************************/
  10. #include "gfx.h"
  11. #include "input.h"
  12. #include "ddutil.h"
  13. /*
  14.  * Externals
  15.  */
  16. extern BOOL             gbUseEmulation;     // user DDHEL or DDHAL ?
  17. extern BOOL gbFullscreen; // window or fullscreen mode ?
  18. extern HWND ghWndMain; // main window
  19. extern DWORD gdwKeys;
  20. extern int              gnProgramState;     // current state of program (rest, splash, active, etc.)
  21. extern RECT grcWindow;          // client window rectangle
  22. extern BOOL gbFullscreen; // fullscreen or window mode ?
  23. extern HINSTANCE ghinst; // application instance handle
  24. extern TCHAR gtszClassName[]; // Duel's class name
  25. /*
  26.  * Globals
  27.  */
  28. LPDIRECTDRAWSURFACE     glpFrontBuffer; // primary surface
  29. LPDIRECTDRAWSURFACE     glpBackBuffer; // back buffer for animation
  30. LPDIRECTDRAWSURFACE glpSplash; // splash screen
  31. LPDIRECTDRAWSURFACE     glpShip0; // ship bitmaps
  32. LPDIRECTDRAWSURFACE     glpShip1;
  33. LPDIRECTDRAWSURFACE     glpShip2;
  34. LPDIRECTDRAWSURFACE     glpShip3;
  35. LPDIRECTDRAWSURFACE     glpNum; // Numbers bitmap
  36. LPDIRECTDRAW            glpDD; // DirectDraw interface
  37. LPDIRECTDRAWPALETTE     glpArtPalette=NULL; // Game screen palette
  38. LPDIRECTDRAWPALETTE     glpSplashPalette=NULL; // Splash screen palette
  39. LPDIRECTDRAWCLIPPER glpClipper=NULL; // Clipper for front buffer
  40. DWORD                   gdwFillColor;
  41. int gnGameBPP; // primary surface bit depth
  42. #ifdef DEBUG
  43. BOOL                    gbHELBlt = FALSE;
  44. #endif
  45. BOOL InitGraphics( void )
  46. {
  47.     DDCAPS          ddcaps;
  48.     HRESULT         ddrval;
  49.     DDSURFACEDESC   ddsd;
  50.     DDSCAPS         ddscaps;
  51. TCHAR tszTitle[MAX_WINDOWTITLE];
  52. LoadString(ghinst, IDS_DUEL_TITLE, tszTitle, MAX_WINDOWTITLE);
  53. // Create a window
  54.     ghWndMain = CreateWindowEx(
  55. WS_EX_APPWINDOW,  // WS_EX_TOPMOST,
  56.         gtszClassName,
  57.         tszTitle,
  58.  // don't show the window yet 
  59.         WS_POPUP |   // non-app window POPUP
  60.         WS_SYSMENU,  // so we get an icon in the tray
  61.         0,
  62.         0,
  63.         GetSystemMetrics(SM_CXSCREEN),
  64.         GetSystemMetrics(SM_CYSCREEN),
  65.         NULL,
  66.         NULL,
  67.         ghinst,
  68.         NULL );
  69.     if( !ghWndMain )
  70.     {
  71.         return FALSE;
  72.     }
  73.     UpdateWindow( ghWndMain );
  74.     SetFocus( ghWndMain );
  75. // ddraw stuff begins here
  76.     if( gbUseEmulation )
  77.         ddrval = DirectDrawCreate( (LPVOID) DDCREATE_EMULATIONONLY, &glpDD, NULL );
  78.     else
  79.         ddrval = DirectDrawCreate( NULL, &glpDD, NULL );
  80.     if( ddrval != DD_OK )
  81.         return ShowError(IDS_DDRAW_ERROR_DDC);
  82. // set access mode based on fullscreen/window
  83. if (gbFullscreen) 
  84. {
  85. ddrval = glpDD->lpVtbl->SetCooperativeLevel( glpDD, ghWndMain,
  86.                             DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
  87. }
  88. else
  89. {
  90. ddrval = glpDD->lpVtbl->SetCooperativeLevel( glpDD, ghWndMain,
  91.                             DDSCL_NORMAL);
  92. }
  93.     if( ddrval != DD_OK )
  94.         return ShowError(IDS_DDRAW_ERROR_SCL);
  95. if (gbFullscreen)
  96. {
  97.     // set the mode to 640 by 480 by 8
  98. ddrval = glpDD->lpVtbl->SetDisplayMode( glpDD, 640, 480, 8 );
  99.     
  100. if( ddrval != DD_OK )
  101.     return ShowError(IDS_DDRAW_ERROR_SDM);
  102. }
  103. else
  104. {
  105. RECT rcWork;
  106. RECT rc;
  107. HDC hdc;
  108. DWORD dwStyle;
  109. //
  110. //  when in rome (I mean when in windows) we should use the
  111. //  current mode
  112. //
  113. hdc = GetDC(NULL);
  114. gnGameBPP = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
  115. ReleaseDC(NULL, hdc);
  116. //
  117. // if we are still a WS_POPUP window we should convert to a
  118. // normal app window so we look like a windows app.
  119. //
  120. dwStyle = GetWindowStyle(ghWndMain);
  121. dwStyle &= ~WS_POPUP;
  122. dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
  123. SetWindowLong(ghWndMain, GWL_STYLE, dwStyle);
  124. // set window size
  125. SetRect(&rc, 0, 0, MAX_DEFWIN_X, MAX_DEFWIN_Y);
  126. AdjustWindowRectEx(&rc,
  127. GetWindowStyle(ghWndMain),
  128. GetMenu(ghWndMain) != NULL,
  129. GetWindowExStyle(ghWndMain));
  130. SetWindowPos(ghWndMain, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
  131. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  132. SetWindowPos(ghWndMain, HWND_NOTOPMOST, 0, 0, 0, 0,
  133. SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  134. //
  135. //  make sure our window does not hang outside of the work area
  136. //  this will make people who have the tray on the top or left
  137. //  happy.
  138. //
  139. SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
  140. GetWindowRect(ghWndMain, &rc);
  141. if (rc.left < rcWork.left) rc.left = rcWork.left;
  142. if (rc.top  < rcWork.top)  rc.top  = rcWork.top;
  143. SetWindowPos(ghWndMain, NULL, rc.left, rc.top, 0, 0,
  144. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  145. }
  146.     // check the color key hardware capabilities
  147.     ddcaps.dwSize = sizeof( ddcaps );
  148. memset( &ddsd, 0, sizeof( ddsd ) );
  149. ddsd.dwSize = sizeof( ddsd );
  150. if (gbFullscreen)
  151. {
  152. // Create surfaces
  153. ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
  154. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
  155.   DDSCAPS_FLIP |
  156.   DDSCAPS_COMPLEX;
  157. ddsd.dwBackBufferCount = 1;
  158. ddrval = glpDD->lpVtbl->CreateSurface( glpDD, &ddsd, &glpFrontBuffer, NULL );
  159. if( ddrval != DD_OK )
  160. return ShowError(IDS_DDRAW_ERROR_CSFB);
  161. // get a pointer to the back buffer
  162. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  163. ddrval = glpFrontBuffer->lpVtbl->GetAttachedSurface(
  164. glpFrontBuffer,
  165. &ddscaps,
  166. &glpBackBuffer );
  167. if( ddrval != DD_OK )
  168. return ShowError(IDS_DDRAW_ERROR_GAS);
  169. }
  170. else
  171. {
  172. // window case, create the primary surface
  173. // and create a backbuffer in offscreen memory
  174. ddsd.dwFlags = DDSD_CAPS;
  175. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  176. ddrval = glpDD->lpVtbl->CreateSurface( glpDD, &ddsd, &glpFrontBuffer, NULL );
  177. if( ddrval != DD_OK )
  178. return ShowError(IDS_DDRAW_ERROR_CSFB);
  179. ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  180. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  181. ddsd.dwWidth = MAX_DEFWIN_X;
  182. ddsd.dwHeight = MAX_DEFWIN_Y;
  183. ddrval = glpDD->lpVtbl->CreateSurface( glpDD, &ddsd, &glpBackBuffer, NULL );
  184. if( ddrval != DD_OK )
  185. return ShowError(IDS_DDRAW_ERROR_CSBB);
  186. ddrval = glpDD->lpVtbl->CreateClipper(glpDD, 0, &glpClipper, NULL);
  187. if( ddrval != DD_OK )
  188. return ShowError(IDS_DDRAW_ERROR_CC);
  189. ddrval = glpClipper->lpVtbl->SetHWnd(glpClipper, 0, ghWndMain);
  190. if( ddrval != DD_OK )
  191. return ShowError(IDS_DDRAW_ERROR_SH);
  192. ddrval = glpFrontBuffer->lpVtbl->SetClipper(glpFrontBuffer, glpClipper);
  193. if( ddrval != DD_OK )
  194. return ShowError(IDS_DDRAW_ERROR_SC);
  195. }
  196.     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
  197.     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  198. #ifdef DEBUG
  199.     if( gbHELBlt )
  200.         ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  201. #endif
  202.     ddsd.dwWidth = 320;
  203.     ddsd.dwHeight = 128;
  204.     ddrval = glpDD->lpVtbl->CreateSurface( glpDD, &ddsd, &glpShip0, NULL );
  205.     if( ddrval != DD_OK )
  206. return ShowError(IDS_DDRAW_ERROR_CSS0);
  207.     ddsd.dwWidth = 320;
  208.     ddsd.dwHeight = 128;
  209.     ddrval = glpDD->lpVtbl->CreateSurface( glpDD, &ddsd, &glpShip1, NULL );
  210.     if( ddrval != DD_OK )
  211. return ShowError(IDS_DDRAW_ERROR_CSS1);
  212.     ddsd.dwWidth = 320;
  213.     ddsd.dwHeight = 128;
  214.     ddrval = glpDD->lpVtbl->CreateSurface( glpDD, &ddsd, &glpShip2, NULL );
  215.     if( ddrval != DD_OK )
  216. return ShowError(IDS_DDRAW_ERROR_CSS2);
  217.     ddsd.dwWidth = 320;
  218.     ddsd.dwHeight = 128;
  219.     ddrval = glpDD->lpVtbl->CreateSurface( glpDD, &ddsd, &glpShip3, NULL );
  220.     if( ddrval != DD_OK )
  221. return ShowError(IDS_DDRAW_ERROR_CSS3);
  222.     ddsd.dwHeight = 16;
  223.     ddrval = glpDD->lpVtbl->CreateSurface( glpDD, &ddsd, &glpNum, NULL );
  224.     if( ddrval != DD_OK )
  225. return ShowError(IDS_DDRAW_ERROR_CSN);
  226.     if( !RestoreSurfaces() )
  227.         return ShowError(IDS_DDRAW_ERROR_RS);
  228.     gdwKeys = 0;
  229. ShowWindow(ghWndMain, SW_SHOW);
  230.     return TRUE;
  231. }
  232. void CleanupGraphics(void)
  233. {
  234.     if( glpShip0 != NULL )
  235. glpShip0->lpVtbl->Release( glpShip0 );
  236.     if( glpShip1 != NULL )
  237. glpShip1->lpVtbl->Release( glpShip1 );
  238.     if( glpShip2 != NULL )
  239. glpShip2->lpVtbl->Release( glpShip2 );
  240.     if( glpShip3 != NULL )
  241. glpShip3->lpVtbl->Release( glpShip3 );
  242.     if( glpNum != NULL )
  243. glpNum->lpVtbl->Release( glpNum );
  244. if (!gbFullscreen && glpClipper)
  245. glpClipper->lpVtbl->Release( glpClipper );
  246.     if( glpFrontBuffer != NULL )
  247. glpFrontBuffer->lpVtbl->Release( glpFrontBuffer );
  248.      if( glpArtPalette != NULL )
  249. glpArtPalette->lpVtbl->Release( glpArtPalette );
  250.     if( glpSplashPalette != NULL )
  251. glpSplashPalette->lpVtbl->Release( glpSplashPalette );
  252.    if( !gbFullscreen && (glpBackBuffer != NULL ))
  253. glpBackBuffer->lpVtbl->Release( glpBackBuffer );
  254.     if( glpDD != NULL )
  255.         glpDD->lpVtbl->Release( glpDD );
  256. }
  257. void bltSplash( LPRECT rc)
  258. {
  259.     HRESULT     ddrval;
  260.     HBITMAP     hbm;
  261.     if( ( glpFrontBuffer == NULL ) ||
  262.         ( glpSplashPalette == NULL ) ||
  263. ( glpBackBuffer == NULL ) )
  264.     {
  265.         return;
  266.     }
  267.     // set the palette before loading the splash screen
  268. glpFrontBuffer->lpVtbl->SetPalette( glpFrontBuffer, glpSplashPalette );
  269.     hbm = (HBITMAP)LoadImage( GetModuleHandle( NULL ), TEXT("SPLASH"), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
  270.     if ( NULL == hbm )
  271. return;
  272.     // if the surface is lost, DDCopyBitmap will fail and the surface will
  273.     // be restored below.
  274.     ddrval = DDCopyBitmap( glpBackBuffer, hbm, 0, 0, 0, 0 );
  275.     DeleteObject( hbm );
  276.     while( 1 )
  277.     {
  278.         if( NULL == rc)
  279. {
  280. ddrval = glpFrontBuffer->lpVtbl->Blt( glpFrontBuffer, 
  281. &grcWindow, glpBackBuffer, NULL, DDBLT_WAIT, NULL);
  282. }
  283. else
  284. {
  285. ddrval = glpFrontBuffer->lpVtbl->Blt( glpFrontBuffer, 
  286. &grcWindow, glpBackBuffer, rc, DDBLT_WAIT, NULL);
  287. }
  288.         if( ddrval == DD_OK )
  289.     return;
  290.         if( ddrval == DDERR_SURFACELOST )
  291.             if( !RestoreSurfaces() )
  292.                 return;
  293.         if( ddrval != DDERR_WASSTILLDRAWING )
  294.             return;
  295.     }
  296. }
  297. void bltScore( char *num, int x, int y )
  298. {
  299.     char *c;
  300.     RECT    src;
  301.     int     i;
  302.     for(c=num; *c != ''; c++)
  303.     {
  304.         i = *c - '0';
  305.         src.left = i*16;
  306.         src.top = 0;
  307.         src.right = src.left + 16;
  308.         src.bottom = src.top + 16;
  309. bltObject( x, y, glpNum, &src, DDBLTFAST_SRCCOLORKEY );
  310.         x += 16;
  311.     }
  312. }
  313. void bltObject( int x, int y, LPDIRECTDRAWSURFACE surf, LPRECT src, DWORD flags )
  314. {
  315.     HRESULT ddrval;
  316.     while( 1 )
  317.     {
  318.         ddrval = glpBackBuffer->lpVtbl->BltFast( glpBackBuffer, x, y, surf, src, flags );
  319.         if( ddrval == DD_OK )
  320.     return;
  321.         if( ddrval == DDERR_SURFACELOST )
  322.             if( !RestoreSurfaces() )
  323.                 return;
  324.         if( ddrval != DDERR_WASSTILLDRAWING )
  325.             return;
  326.     }
  327. }
  328. void EraseScreen( void )
  329. {
  330.     DDBLTFX     ddbltfx;
  331.     HRESULT     ddrval;
  332.     // Erase the background
  333.     ddbltfx.dwSize = sizeof( ddbltfx );
  334.     ddbltfx.dwFillColor = gdwFillColor;
  335.     while( 1 )
  336.     {
  337.         ddrval = glpBackBuffer->lpVtbl->Blt( glpBackBuffer, NULL, NULL,
  338.                  NULL, DDBLT_COLORFILL, &ddbltfx );
  339.         if( ddrval == DD_OK )
  340.         {
  341.             break;
  342.         }
  343.         if( ddrval == DDERR_SURFACELOST )
  344.         {
  345.             if( !RestoreSurfaces() )
  346.                 return;
  347.         }
  348.         if( ddrval != DDERR_WASSTILLDRAWING )
  349.         {
  350.             return;
  351.         }
  352.     }
  353. }
  354. void FlipScreen( void )
  355. {
  356.     HRESULT     ddrval;
  357.     // Flip the surfaces
  358. if (gbFullscreen)
  359. {
  360. while( 1 )
  361. {
  362. ddrval = glpFrontBuffer->lpVtbl->Flip( glpFrontBuffer, NULL, 0 );
  363. if( ddrval == DD_OK )
  364. {
  365. break;
  366. }
  367. if( ddrval == DDERR_SURFACELOST )
  368. {
  369. if( !RestoreSurfaces() )
  370. {
  371. return;
  372. }
  373. }
  374. if( ddrval != DDERR_WASSTILLDRAWING )
  375. {
  376. break;
  377. }
  378. }
  379.     }
  380. else
  381. {
  382.     ddrval = IDirectDrawSurface_Blt(
  383.                     glpFrontBuffer,          // dest surface
  384.                     &grcWindow,              // dest rect
  385.                     glpBackBuffer,           // src surface
  386.                     NULL,                   // src rect (all of it)
  387.                     DDBLT_WAIT,
  388.                     NULL);
  389. }
  390. }
  391. BOOL RestoreSurfaces( void )
  392. {
  393.     HRESULT ddrval;
  394.     HBITMAP     hbm;
  395.     ddrval = glpFrontBuffer->lpVtbl->Restore(glpFrontBuffer);
  396.     if( ddrval != DD_OK )
  397.         return FALSE;
  398. ddrval = glpBackBuffer->lpVtbl->Restore(glpBackBuffer);
  399. if( ddrval != DD_OK )
  400. return FALSE;
  401.     ddrval = glpShip0->lpVtbl->Restore(glpShip0);
  402.     if( ddrval != DD_OK )
  403.         return FALSE;
  404.     ddrval = glpShip1->lpVtbl->Restore(glpShip1);
  405.     if( ddrval != DD_OK )
  406.         return FALSE;
  407.     ddrval = glpShip2->lpVtbl->Restore(glpShip2);
  408.     if( ddrval != DD_OK )
  409.         return FALSE;
  410.     ddrval = glpShip3->lpVtbl->Restore(glpShip3);
  411.     if( ddrval != DD_OK )
  412.         return FALSE;
  413.     ddrval = glpNum->lpVtbl->Restore(glpNum);
  414.     if( ddrval != DD_OK )
  415.         return FALSE;
  416.     // Create and set the palette for the splash bitmap
  417.     glpSplashPalette = DDLoadPalette( glpDD, TEXT("SPLASH") );
  418.     if( NULL == glpSplashPalette )
  419. return FALSE;
  420.     // Create and set the palette for the art bitmap
  421.     glpArtPalette = DDLoadPalette( glpDD, TEXT("Duel8") );
  422.     if( NULL == glpArtPalette )
  423. return FALSE;
  424.     // set the palette before loading the art
  425.     glpFrontBuffer->lpVtbl->SetPalette( glpFrontBuffer, glpArtPalette );
  426.     hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL), TEXT("Duel8"), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION );
  427.     if( NULL == hbm )
  428.         return FALSE;
  429.     ddrval = DDCopyBitmap( glpShip0, hbm, 0, 0, 320, 128 );
  430.     if( ddrval != DD_OK )
  431.     {
  432.         DeleteObject( hbm );
  433. return FALSE;
  434.     }
  435.     ddrval = DDCopyBitmap( glpShip1, hbm, 0, 128, 320, 128 );
  436.     if( ddrval != DD_OK )
  437.     {
  438.         DeleteObject( hbm );
  439. return FALSE;
  440.     }
  441.     ddrval = DDCopyBitmap( glpShip2, hbm, 0, 256, 320, 128 );
  442.     if( ddrval != DD_OK )
  443.     {
  444.         DeleteObject( hbm );
  445. return FALSE;
  446.     }
  447.     ddrval = DDCopyBitmap( glpShip3, hbm, 0, 384, 320, 128 );
  448.     if( ddrval != DD_OK )
  449.     {
  450.         DeleteObject( hbm );
  451. return FALSE;
  452.     }
  453.     ddrval = DDCopyBitmap( glpNum, hbm, 0, 512, 320, 16 );
  454.     if( ddrval != DD_OK )
  455.     {
  456.         DeleteObject( hbm );
  457. return FALSE;
  458.     }
  459.     DeleteObject( hbm );
  460.     // set colorfill colors and color gdwKeys according to bitmap contents
  461.     gdwFillColor = DDColorMatch( glpShip0, CLR_INVALID );
  462.     
  463.     DDSetColorKey( glpShip0, CLR_INVALID );
  464.     DDSetColorKey( glpShip1, CLR_INVALID );
  465.     DDSetColorKey( glpShip2, CLR_INVALID );
  466.     DDSetColorKey( glpShip3, CLR_INVALID );
  467.     DDSetColorKey( glpNum, CLR_INVALID );
  468.     return TRUE;
  469. }
  470. void SetGamePalette(void)
  471. {
  472. if (glpFrontBuffer)
  473. glpFrontBuffer->lpVtbl->SetPalette( glpFrontBuffer, glpArtPalette );
  474. }
  475. void FlipToGDI(void)
  476. {
  477. if (glpDD) 
  478. glpDD->lpVtbl->FlipToGDISurface( glpDD );
  479. }