Source code of Windows XP (NT5)
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.

844 lines
21 KiB

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