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.

1057 lines
26 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: winfox.c
  7. * Content: Windows fox sample game
  8. *
  9. ***************************************************************************/
  10. #include "foxbear.h"
  11. #include "rcids.h" // for FOX_ICON
  12. LPDIRECTDRAWSURFACE lpFrontBuffer;
  13. LPDIRECTDRAWSURFACE lpBackBuffer;
  14. LPDIRECTDRAWCLIPPER lpClipper;
  15. LPDIRECTDRAWSURFACE lpStretchBuffer;
  16. LPDIRECTDRAWSURFACE lpFrameRate;
  17. LPDIRECTDRAWSURFACE lpInfo;
  18. LPDIRECTDRAWPALETTE lpPalette;
  19. LPDIRECTDRAW lpDD;
  20. SHORT lastInput = 0;
  21. HWND hWndMain;
  22. RECT rcWindow;
  23. BOOL bShowFrameCount=TRUE;
  24. BOOL bIsActive;
  25. BOOL bPaused;
  26. BOOL bStretch;
  27. BOOL bFullscreen=TRUE;
  28. BOOL bStress=FALSE; // just keep running if true
  29. BOOL bHelp=FALSE; // help requested
  30. RECT GameRect; // game rect
  31. SIZE GameSize; // game is this size
  32. SIZE GameMode; // display mode size
  33. UINT GameBPP; // the bpp we want
  34. DWORD dwColorKey; // our color key
  35. DWORD AveFrameRate;
  36. DWORD AveFrameRateCount;
  37. BOOL bWantSound = TRUE;
  38. #define OUR_APP_NAME "Win Fox Application"
  39. #define ODS OutputDebugString
  40. BOOL InitGame(void);
  41. void ExitGame(void);
  42. void initNumSurface(void);
  43. /*
  44. * PauseGame()
  45. */
  46. void PauseGame()
  47. {
  48. Msg("**** PAUSE");
  49. bPaused = TRUE;
  50. InvalidateRect(hWndMain, NULL, TRUE);
  51. }
  52. /*
  53. * UnPauseGame()
  54. */
  55. void UnPauseGame()
  56. {
  57. if (GetForegroundWindow() == hWndMain)
  58. {
  59. Msg("**** UNPAUSE");
  60. bPaused = FALSE;
  61. }
  62. }
  63. /*
  64. * RestoreGame()
  65. */
  66. BOOL RestoreGame()
  67. {
  68. if (lpFrontBuffer == NULL || IDirectDrawSurface_Restore(lpFrontBuffer) != DD_OK)
  69. {
  70. Msg("***** cant restore FrontBuffer");
  71. return FALSE;
  72. }
  73. if (!bFullscreen)
  74. {
  75. if (lpBackBuffer == NULL || IDirectDrawSurface_Restore(lpBackBuffer) != DD_OK)
  76. {
  77. Msg("***** cant restore BackBuffer");
  78. return FALSE;
  79. }
  80. }
  81. if (lpStretchBuffer && IDirectDrawSurface_Restore(lpStretchBuffer) != DD_OK)
  82. {
  83. Msg("***** cant restore StretchBuffer");
  84. return FALSE;
  85. }
  86. if (lpFrameRate == NULL || lpInfo == NULL ||
  87. IDirectDrawSurface_Restore(lpFrameRate) != DD_OK ||
  88. IDirectDrawSurface_Restore(lpInfo) != DD_OK)
  89. {
  90. Msg("***** cant restore frame rate stuff");
  91. return FALSE;
  92. }
  93. initNumSurface();
  94. if (!gfxRestoreAll())
  95. {
  96. Msg("***** cant restore art");
  97. return FALSE;
  98. }
  99. return TRUE;
  100. }
  101. /*
  102. * ProcessFox
  103. */
  104. BOOL ProcessFox(SHORT sInput)
  105. {
  106. if ((lpFrontBuffer && IDirectDrawSurface_IsLost(lpFrontBuffer) == DDERR_SURFACELOST) ||
  107. (lpBackBuffer && IDirectDrawSurface_IsLost(lpBackBuffer) == DDERR_SURFACELOST))
  108. {
  109. if (!RestoreGame())
  110. {
  111. PauseGame();
  112. return FALSE;
  113. }
  114. }
  115. ProcessInput(sInput);
  116. NewGameFrame();
  117. return TRUE;
  118. } /* ProcessFox */
  119. static HFONT hFont;
  120. DWORD dwFrameCount;
  121. DWORD dwFrameTime;
  122. DWORD dwFrames;
  123. DWORD dwFramesLast;
  124. SIZE sizeFPS;
  125. SIZE sizeINFO;
  126. int FrameRateX;
  127. char szFPS[] = "FPS %02d";
  128. char szINFO[] = "%dx%dx%d%s F6=mode F8=x2 ALT+ENTER=Window";
  129. char szINFOW[] = "%dx%dx%d%s F6=mode F8=x2 ALT+ENTER=Fullscreen";
  130. char szFrameRate[128];
  131. char szInfo[128];
  132. COLORREF InfoColor = RGB(0,152,245);
  133. COLORREF FrameRateColor = RGB(255,255,0);
  134. COLORREF BackColor = RGB(255,255,255);
  135. /*
  136. * initNumSurface
  137. */
  138. void initNumSurface( void )
  139. {
  140. HDC hdc;
  141. RECT rc;
  142. int len;
  143. dwFramesLast = 0;
  144. len = wsprintf(szFrameRate, szFPS, 0, 0);
  145. if( lpFrameRate && IDirectDrawSurface_GetDC(lpFrameRate, &hdc ) == DD_OK )
  146. {
  147. SelectObject(hdc, hFont);
  148. SetTextColor(hdc, FrameRateColor);
  149. SetBkColor(hdc, BackColor);
  150. SetBkMode(hdc, OPAQUE);
  151. SetRect(&rc, 0, 0, 10000, 10000);
  152. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, szFrameRate, len, NULL);
  153. GetTextExtentPoint(hdc, szFrameRate, 4, &sizeFPS);
  154. FrameRateX = sizeFPS.cx;
  155. GetTextExtentPoint(hdc, szFrameRate, len, &sizeFPS);
  156. IDirectDrawSurface_ReleaseDC(lpFrameRate, hdc);
  157. }
  158. if (bFullscreen)
  159. len = wsprintf(szInfo, szINFO,
  160. GameSize.cx, GameSize.cy, GameBPP,bStretch ? " x2" : "");
  161. else
  162. len = wsprintf(szInfo, szINFOW,
  163. GameSize.cx, GameSize.cy, GameBPP,bStretch ? " x2" : "");
  164. if( lpInfo && IDirectDrawSurface_GetDC(lpInfo, &hdc ) == DD_OK )
  165. {
  166. SelectObject(hdc, hFont);
  167. SetTextColor(hdc, InfoColor);
  168. SetBkColor(hdc, BackColor);
  169. SetBkMode(hdc, OPAQUE);
  170. SetRect(&rc, 0, 0, 10000, 10000);
  171. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, szInfo, len, NULL);
  172. GetTextExtentPoint(hdc, szInfo, len, &sizeINFO);
  173. IDirectDrawSurface_ReleaseDC(lpInfo, hdc);
  174. }
  175. } /* initNumSurface */
  176. /*
  177. * makeFontStuff
  178. */
  179. static BOOL makeFontStuff( void )
  180. {
  181. DDCOLORKEY ddck;
  182. HDC hdc;
  183. if (hFont != NULL)
  184. {
  185. DeleteObject(hFont);
  186. }
  187. hFont = CreateFont(
  188. GameSize.cx <= 512 ? 12 : 24,
  189. 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
  190. ANSI_CHARSET,
  191. OUT_DEFAULT_PRECIS,
  192. CLIP_DEFAULT_PRECIS,
  193. NONANTIALIASED_QUALITY, // DEFAULT_QUALITY,
  194. VARIABLE_PITCH,
  195. "Arial" );
  196. /*
  197. * make a sample string so we can measure it with the current font.
  198. */
  199. initNumSurface();
  200. hdc = GetDC(NULL);
  201. SelectObject(hdc, hFont);
  202. GetTextExtentPoint(hdc, szFrameRate, lstrlen(szFrameRate), &sizeFPS);
  203. GetTextExtentPoint(hdc, szInfo, lstrlen(szInfo), &sizeINFO);
  204. ReleaseDC(NULL, hdc);
  205. /*
  206. * Create a surface to copy our bits to.
  207. */
  208. lpFrameRate = DDCreateSurface(sizeFPS.cx, sizeFPS.cy, FALSE,TRUE);
  209. lpInfo = DDCreateSurface(sizeINFO.cx, sizeINFO.cy, FALSE,TRUE);
  210. if( lpFrameRate == NULL || lpInfo == NULL )
  211. {
  212. return FALSE;
  213. }
  214. /*
  215. * now set the color key, we use a totaly different color than
  216. * the rest of the app, just to be different so drivers dont always
  217. * get white or black as the color key...
  218. *
  219. * dont forget when running on a dest colorkey device, we need
  220. * to use the same color key as the rest of the app.
  221. */
  222. if( bTransDest )
  223. BackColor = RGB(255,255,255);
  224. else
  225. BackColor = RGB(128,64,255);
  226. ddck.dwColorSpaceLowValue = DDColorMatch(lpInfo, BackColor);
  227. ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
  228. IDirectDrawSurface_SetColorKey( lpInfo, DDCKEY_SRCBLT, &ddck);
  229. IDirectDrawSurface_SetColorKey( lpFrameRate, DDCKEY_SRCBLT, &ddck);
  230. /*
  231. * now draw the text for real
  232. */
  233. initNumSurface();
  234. return TRUE;
  235. }
  236. /*
  237. * DisplayFrameRate
  238. */
  239. void DisplayFrameRate( void )
  240. {
  241. DWORD time2;
  242. char buff[256];
  243. HDC hdc;
  244. HRESULT ddrval;
  245. RECT rc;
  246. DWORD dw;
  247. if( !bShowFrameCount )
  248. {
  249. return;
  250. }
  251. dwFrameCount++;
  252. time2 = timeGetTime() - dwFrameTime;
  253. if( time2 > 1000 )
  254. {
  255. dwFrames = (dwFrameCount*1000)/time2;
  256. dwFrameTime = timeGetTime();
  257. dwFrameCount = 0;
  258. AveFrameRate += dwFrames;
  259. AveFrameRateCount++;
  260. }
  261. if( dwFrames == 0 )
  262. {
  263. return;
  264. }
  265. if( dwFrames != dwFramesLast )
  266. {
  267. dwFramesLast = dwFrames;
  268. if( IDirectDrawSurface_GetDC(lpFrameRate, &hdc ) == DD_OK )
  269. {
  270. buff[0] = (char)((dwFrames / 10) + '0');
  271. buff[1] = (char)((dwFrames % 10) + '0');
  272. SelectObject(hdc, hFont);
  273. SetTextColor(hdc, FrameRateColor);
  274. SetBkColor(hdc, BackColor);
  275. TextOut(hdc, FrameRateX, 0, buff, 2);
  276. IDirectDrawSurface_ReleaseDC(lpFrameRate, hdc);
  277. }
  278. }
  279. /*
  280. * put the text on the back buffer.
  281. */
  282. if (bTransDest)
  283. dw = DDBLTFAST_DESTCOLORKEY | DDBLTFAST_WAIT;
  284. else
  285. dw = DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT;
  286. SetRect(&rc, 0, 0, sizeFPS.cx, sizeFPS.cy);
  287. ddrval = IDirectDrawSurface_BltFast(lpBackBuffer,
  288. GameRect.left + (GameSize.cx - sizeFPS.cx)/2, GameRect.top + 20,
  289. lpFrameRate, &rc, dw);
  290. SetRect(&rc, 0, 0, sizeINFO.cx, sizeINFO.cy);
  291. ddrval = IDirectDrawSurface_BltFast(lpBackBuffer,
  292. GameRect.left + 10, GameRect.bottom - sizeINFO.cy - 10,
  293. lpInfo, &rc, dw);
  294. } /* DisplayFrameRate */
  295. /*
  296. * MainWndProc
  297. *
  298. * Callback for all Windows messages
  299. */
  300. long FAR PASCAL MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
  301. {
  302. PAINTSTRUCT ps;
  303. HDC hdc;
  304. int i;
  305. switch( message )
  306. {
  307. case WM_SIZE:
  308. case WM_MOVE:
  309. if (IsIconic(hWnd))
  310. {
  311. Msg("FoxBear is minimized, pausing");
  312. PauseGame();
  313. }
  314. if (bFullscreen)
  315. {
  316. SetRect(&rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
  317. }
  318. else
  319. {
  320. GetClientRect(hWnd, &rcWindow);
  321. ClientToScreen(hWnd, (LPPOINT)&rcWindow);
  322. ClientToScreen(hWnd, (LPPOINT)&rcWindow+1);
  323. }
  324. Msg("WINDOW RECT: [%d,%d,%d,%d]", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom);
  325. break;
  326. case WM_ACTIVATEAPP:
  327. bIsActive = (BOOL)wParam && GetForegroundWindow() == hWnd;
  328. if (bIsActive)
  329. Msg("FoxBear is active");
  330. else
  331. Msg("FoxBear is not active");
  332. //
  333. // while we were not-active something bad happened that caused us
  334. // to pause, like a surface restore failing or we got a palette
  335. // changed, now that we are active try to fix things
  336. //
  337. if (bPaused && bIsActive)
  338. {
  339. if (RestoreGame())
  340. {
  341. UnPauseGame();
  342. }
  343. else
  344. {
  345. if (GetForegroundWindow() == hWnd)
  346. {
  347. //
  348. // we are unable to restore, this can happen when
  349. // the screen resolution or bitdepth has changed
  350. // we just reload all the art again and re-create
  351. // the front and back buffers. this is a little
  352. // overkill we could handle a screen res change by
  353. // just recreating the front and back buffers we dont
  354. // need to redo the art, but this is way easier.
  355. //
  356. if (InitGame())
  357. {
  358. UnPauseGame();
  359. }
  360. }
  361. }
  362. }
  363. break;
  364. case WM_QUERYNEWPALETTE:
  365. //
  366. // we are getting the palette focus, select our palette
  367. //
  368. if (!bFullscreen && lpPalette && lpFrontBuffer)
  369. {
  370. HRESULT ddrval;
  371. ddrval = IDirectDrawSurface_SetPalette(lpFrontBuffer,lpPalette);
  372. if( ddrval == DDERR_SURFACELOST )
  373. {
  374. IDirectDrawSurface_Restore( lpFrontBuffer );
  375. ddrval= IDirectDrawSurface_SetPalette(lpFrontBuffer,lpPalette);
  376. if( ddrval == DDERR_SURFACELOST )
  377. {
  378. Msg(" Failed to restore palette after second try");
  379. }
  380. }
  381. //
  382. // Restore normal title if palette is ours
  383. //
  384. if( ddrval == DD_OK )
  385. {
  386. SetWindowText( hWnd, OUR_APP_NAME );
  387. }
  388. }
  389. break;
  390. case WM_PALETTECHANGED:
  391. //
  392. // if another app changed the palette we dont have full control
  393. // of the palette. NOTE this only applies for FoxBear in a window
  394. // when we are fullscreen we get all the palette all of the time.
  395. //
  396. if ((HWND)wParam != hWnd)
  397. {
  398. if( !bFullscreen )
  399. {
  400. if( !bStress )
  401. {
  402. Msg("***** PALETTE CHANGED, PAUSING GAME");
  403. PauseGame();
  404. }
  405. else
  406. {
  407. Msg("Lost palette but continuing");
  408. SetWindowText( hWnd, OUR_APP_NAME
  409. " - palette changed COLORS PROBABLY WRONG" );
  410. }
  411. }
  412. }
  413. break;
  414. case WM_DISPLAYCHANGE:
  415. break;
  416. case WM_CREATE:
  417. break;
  418. case WM_SETCURSOR:
  419. if (bFullscreen && bIsActive)
  420. {
  421. SetCursor(NULL);
  422. return TRUE;
  423. }
  424. break;
  425. case WM_SYSKEYUP:
  426. switch( wParam )
  427. {
  428. // handle ALT+ENTER (fullscreen)
  429. case VK_RETURN:
  430. bFullscreen = !bFullscreen;
  431. ExitGame();
  432. DDDisable(TRUE); // destroy DirectDraw object
  433. InitGame();
  434. break;
  435. }
  436. break;
  437. case WM_KEYDOWN:
  438. switch( wParam )
  439. {
  440. case VK_NUMPAD5:
  441. lastInput=KEY_STOP;
  442. break;
  443. case VK_DOWN:
  444. case VK_NUMPAD2:
  445. lastInput=KEY_DOWN;
  446. break;
  447. case VK_LEFT:
  448. case VK_NUMPAD4:
  449. lastInput=KEY_LEFT;
  450. break;
  451. case VK_RIGHT:
  452. case VK_NUMPAD6:
  453. lastInput=KEY_RIGHT;
  454. break;
  455. case VK_UP:
  456. case VK_NUMPAD8:
  457. lastInput=KEY_UP;
  458. break;
  459. case VK_HOME:
  460. case VK_NUMPAD7:
  461. lastInput=KEY_JUMP;
  462. break;
  463. case VK_NUMPAD3:
  464. lastInput=KEY_THROW;
  465. break;
  466. case VK_F5:
  467. bShowFrameCount = !bShowFrameCount;
  468. if( bShowFrameCount )
  469. {
  470. dwFrameCount = 0;
  471. dwFrameTime = timeGetTime();
  472. }
  473. break;
  474. case VK_F6:
  475. //
  476. // find our current mode in the mode list
  477. //
  478. if(bFullscreen)
  479. {
  480. for (i=0; i<NumModes; i++)
  481. {
  482. if (ModeList[i].bpp == (int)GameBPP &&
  483. ModeList[i].w == GameSize.cx &&
  484. ModeList[i].h == GameSize.cy)
  485. {
  486. break;
  487. }
  488. }
  489. }else
  490. {
  491. for (i=0; i<NumModes; i++)
  492. {
  493. if (ModeList[i].w == GameSize.cx &&
  494. ModeList[i].h == GameSize.cy)
  495. {
  496. break;
  497. }
  498. }
  499. }
  500. //
  501. // now step to the next mode, wrapping to the first one.
  502. //
  503. if (++i >= NumModes)
  504. i = 0;
  505. Msg("ModeList %d %d",i,NumModes);
  506. GameMode.cx = ModeList[i].w;
  507. GameMode.cy = ModeList[i].h;
  508. GameBPP = ModeList[i].bpp;
  509. bStretch = FALSE;
  510. InitGame();
  511. break;
  512. case VK_F7:
  513. GameBPP = GameBPP == 8 ? 16 : 8;
  514. InitGame();
  515. break;
  516. case VK_F8:
  517. if (bFullscreen)
  518. {
  519. bStretch = !bStretch;
  520. InitGame();
  521. }
  522. else
  523. {
  524. RECT rc;
  525. GetClientRect(hWnd, &rc);
  526. bStretch = (rc.right != GameSize.cx) ||
  527. (rc.bottom != GameSize.cy);
  528. if (bStretch = !bStretch)
  529. SetRect(&rc, 0, 0, GameMode.cx*2, GameMode.cy*2);
  530. else
  531. SetRect(&rc, 0, 0, GameMode.cx, GameMode.cy);
  532. AdjustWindowRectEx(&rc,
  533. GetWindowStyle(hWnd),
  534. GetMenu(hWnd) != NULL,
  535. GetWindowExStyle(hWnd));
  536. SetWindowPos(hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
  537. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  538. }
  539. break;
  540. case VK_F4:
  541. // treat F4 like ALT+ENTER (fullscreen)
  542. PostMessage(hWnd, WM_SYSKEYUP, VK_RETURN, 0);
  543. break;
  544. case VK_F3:
  545. bPaused = !bPaused;
  546. break;
  547. case VK_ESCAPE:
  548. case VK_F12:
  549. PostMessage(hWnd, WM_CLOSE, 0, 0);
  550. return 0;
  551. }
  552. break;
  553. case WM_PAINT:
  554. hdc = BeginPaint( hWnd, &ps );
  555. if (bPaused)
  556. {
  557. char *sz = "Game is paused, this is not a bug.";
  558. TextOut(ps.hdc, 0, 0, sz, lstrlen(sz));
  559. }
  560. EndPaint( hWnd, &ps );
  561. return 1;
  562. case WM_DESTROY:
  563. hWndMain = NULL;
  564. lastInput=0;
  565. DestroyGame(); // end of game
  566. DDDisable(TRUE); // destroy DirectDraw object
  567. PostQuitMessage( 0 );
  568. break;
  569. }
  570. return DefWindowProc(hWnd, message, wParam, lParam);
  571. } /* MainWndProc */
  572. /*
  573. * initApplication
  574. *
  575. * Do that Windows initialization stuff...
  576. */
  577. static BOOL initApplication( HINSTANCE hInstance, int nCmdShow )
  578. {
  579. WNDCLASS wc;
  580. BOOL rc;
  581. wc.style = CS_DBLCLKS;
  582. wc.lpfnWndProc = MainWndProc;
  583. wc.cbClsExtra = 0;
  584. wc.cbWndExtra = 0;
  585. wc.hInstance = hInstance;
  586. wc.hIcon = LoadIcon( hInstance, MAKEINTATOM(FOX_ICON));
  587. wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  588. wc.hbrBackground = GetStockObject(BLACK_BRUSH);
  589. wc.lpszMenuName = NULL;
  590. wc.lpszClassName = "WinFoxClass";
  591. rc = RegisterClass( &wc );
  592. if( !rc )
  593. {
  594. return FALSE;
  595. }
  596. hWndMain = CreateWindowEx(
  597. WS_EX_APPWINDOW,
  598. "WinFoxClass",
  599. OUR_APP_NAME,
  600. WS_VISIBLE | // so we dont have to call ShowWindow
  601. WS_SYSMENU | // so we get a icon in in our tray button
  602. WS_POPUP,
  603. 0,
  604. 0,
  605. GetSystemMetrics(SM_CXSCREEN),
  606. GetSystemMetrics(SM_CYSCREEN),
  607. NULL,
  608. NULL,
  609. hInstance,
  610. NULL );
  611. if( !hWndMain )
  612. {
  613. return FALSE;
  614. }
  615. UpdateWindow( hWndMain );
  616. SetFocus( hWndMain );
  617. return TRUE;
  618. } /* initApplication */
  619. /*
  620. * ExitGame
  621. *
  622. * Exiting current game, clean up
  623. */
  624. void ExitGame( void )
  625. {
  626. if( lpFrameRate )
  627. {
  628. IDirectDrawSurface_Release(lpFrameRate);
  629. lpFrameRate = NULL;
  630. }
  631. if( lpInfo )
  632. {
  633. IDirectDrawSurface_Release(lpInfo);
  634. lpInfo = NULL;
  635. }
  636. if( lpPalette )
  637. {
  638. IDirectDrawSurface_Release(lpPalette);
  639. lpPalette = NULL;
  640. }
  641. DestroyGame();
  642. } /* ExitGame */
  643. /*
  644. * InitGame
  645. *
  646. * Initializing current game
  647. */
  648. BOOL InitGame( void )
  649. {
  650. ExitGame();
  651. GameSize = GameMode;
  652. /*
  653. * initialize sound
  654. */
  655. InitSound( hWndMain );
  656. /*
  657. * init DirectDraw, set mode, ...
  658. * NOTE GameMode might be set to 640x480 if we cant get the asked for mode.
  659. */
  660. if( !PreInitializeGame() )
  661. {
  662. return FALSE;
  663. }
  664. if (bStretch && bFullscreen)
  665. {
  666. GameSize.cx = GameMode.cx / 2;
  667. GameSize.cy = GameMode.cy / 2;
  668. GameRect.left = GameMode.cx - GameSize.cx;
  669. GameRect.top = GameMode.cy - GameSize.cy;
  670. GameRect.right = GameMode.cx;
  671. GameRect.bottom = GameMode.cy;
  672. if (lpStretchBuffer)
  673. Msg("Stretching using a system-memory stretch buffer");
  674. else
  675. Msg("Stretching using a VRAM->VRAM blt");
  676. }
  677. else
  678. {
  679. GameRect.left = (GameMode.cx - GameSize.cx) / 2;
  680. GameRect.top = (GameMode.cy - GameSize.cy) / 2;
  681. GameRect.right = GameRect.left + GameSize.cx;
  682. GameRect.bottom = GameRect.top + GameSize.cy;
  683. }
  684. /*
  685. * setup our palette
  686. */
  687. if( GameBPP == 8 )
  688. {
  689. lpPalette = ReadPalFile( NULL ); // create a 332 palette
  690. if( lpPalette == NULL )
  691. {
  692. Msg( "Palette create failed" );
  693. return FALSE;
  694. }
  695. IDirectDrawSurface_SetPalette( lpFrontBuffer, lpPalette );
  696. }
  697. /*
  698. * load all the art and things.
  699. */
  700. if( !InitializeGame() )
  701. {
  702. return FALSE;
  703. }
  704. /*
  705. * init our code to draw the FPS
  706. */
  707. makeFontStuff();
  708. /*
  709. * spew some stats
  710. */
  711. {
  712. DDCAPS ddcaps;
  713. ddcaps.dwSize = sizeof( ddcaps );
  714. IDirectDraw_GetCaps( lpDD, &ddcaps, NULL );
  715. Msg( "Total=%ld, Free VRAM=%ld", ddcaps.dwVidMemTotal, ddcaps.dwVidMemFree );
  716. Msg( "Used = %ld", ddcaps.dwVidMemTotal- ddcaps.dwVidMemFree );
  717. }
  718. return TRUE;
  719. } /* InitGame */
  720. #define IS_NUM(c) ((c) >= '0' && (c) <= '9')
  721. #define IS_SPACE(c) ((c) == ' ' || (c) == '\r' || (c) == '\n' || (c) == '\t' || (c) == 'x')
  722. int getint(char**p, int def)
  723. {
  724. int i=0;
  725. while (IS_SPACE(**p))
  726. (*p)++;
  727. if (!IS_NUM(**p))
  728. return def;
  729. while (IS_NUM(**p))
  730. i = i*10 + *(*p)++ - '0';
  731. while (IS_SPACE(**p))
  732. (*p)++;
  733. return i;
  734. }
  735. /*
  736. * WinMain
  737. */
  738. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
  739. int nCmdShow )
  740. {
  741. MSG msg;
  742. while( lpCmdLine[0] == '-' )
  743. {
  744. int iMoviePos = 0;
  745. BOOL bDone = FALSE;
  746. lpCmdLine++;
  747. switch (*lpCmdLine++)
  748. {
  749. case 'c':
  750. bCamera = TRUE;
  751. break;
  752. case 'm':
  753. bMovie = TRUE;
  754. for (;!bDone;) {
  755. switch (*lpCmdLine) {
  756. case ' ':
  757. case 0:
  758. case '-':
  759. case '\n':
  760. case '\r':
  761. bDone = TRUE;
  762. break;
  763. default:
  764. wszMovie[iMoviePos++] = (unsigned char)*lpCmdLine++;
  765. break;
  766. }
  767. }
  768. wszMovie[iMoviePos] = 0;
  769. break;
  770. case 'e':
  771. bUseEmulation = TRUE;
  772. break;
  773. case 'w':
  774. bFullscreen = FALSE;
  775. break;
  776. case 'f':
  777. bFullscreen = TRUE;
  778. break;
  779. case '1':
  780. CmdLineBufferCount = 1;
  781. break;
  782. case '2':
  783. case 'd':
  784. CmdLineBufferCount = 2;
  785. break;
  786. case '3':
  787. CmdLineBufferCount = 3;
  788. break;
  789. case 's':
  790. bStretch = TRUE;
  791. break;
  792. case 'S':
  793. bWantSound = FALSE;
  794. break;
  795. case 'x':
  796. bStress= TRUE;
  797. break;
  798. case '?':
  799. bHelp= TRUE;
  800. bFullscreen= FALSE; // give help in windowed mode
  801. break;
  802. }
  803. while( IS_SPACE(*lpCmdLine) )
  804. {
  805. lpCmdLine++;
  806. }
  807. }
  808. GameMode.cx = getint(&lpCmdLine, 640);
  809. GameMode.cy = getint(&lpCmdLine, 480);
  810. GameBPP = getint(&lpCmdLine, 8);
  811. /*
  812. * create window and other windows things
  813. */
  814. if( !initApplication(hInstance, nCmdShow) )
  815. {
  816. return FALSE;
  817. }
  818. /*
  819. * Give user help if asked for
  820. *
  821. * This is ugly for now because the whole screen is black
  822. * except for the popup box. This could be fixed with some
  823. * work to get the window size right when it was created instead
  824. * of delaying that work. see ddraw.c
  825. *
  826. */
  827. if( bHelp )
  828. {
  829. MessageBox(hWndMain,
  830. "F12 - Quit\n"
  831. "NUMPAD 2 - crouch\n"
  832. "NUMPAD 3 - apple\n"
  833. "NUMPAD 4 - right\n"
  834. "NUMPAD 5 - stop\n"
  835. "NUMPAD 6 - left\n"
  836. "NUMPAD 7 - jump\n"
  837. "\n"
  838. "Command line parameters\n"
  839. "\n"
  840. "-e Use emulator\n"
  841. "-S No Sound\n"
  842. "-1 No backbuffer\n"
  843. "-2 One backbuffer\n"
  844. "-4 Three backbuffers\n"
  845. "-s Use stretch\n"
  846. "-x Demo or stress mode\n"
  847. "-mfoo.bar Movie name\n"
  848. "-c Overlay camera input\n",
  849. OUR_APP_NAME, MB_OK );
  850. }
  851. /*
  852. * initialize for game play
  853. */
  854. if( !InitGame() )
  855. {
  856. return FALSE;
  857. }
  858. dwFrameTime = timeGetTime();
  859. while( 1 )
  860. {
  861. if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
  862. {
  863. if (!GetMessage( &msg, NULL, 0, 0))
  864. {
  865. break;
  866. }
  867. TranslateMessage(&msg);
  868. DispatchMessage(&msg);
  869. }
  870. else if (!bPaused && (bIsActive || !bFullscreen))
  871. {
  872. ProcessFox(lastInput);
  873. lastInput=0;
  874. }
  875. else
  876. {
  877. WaitMessage();
  878. }
  879. }
  880. if (AveFrameRateCount)
  881. {
  882. AveFrameRate = AveFrameRate / AveFrameRateCount;
  883. Msg("Average frame rate: %d", AveFrameRate);
  884. }
  885. return msg.wParam;
  886. } /* WinMain */
  887. #ifdef DEBUG
  888. /*
  889. * Msg
  890. */
  891. void __cdecl Msg( LPSTR fmt, ... )
  892. {
  893. char buff[256];
  894. va_list va;
  895. va_start(va, fmt);
  896. //
  897. // format message with header
  898. //
  899. lstrcpy( buff, "FOXBEAR:" );
  900. wvsprintf( &buff[lstrlen(buff)], fmt, va );
  901. lstrcat( buff, "\r\n" );
  902. //
  903. // To the debugger unless we need to be quiet
  904. //
  905. if( !bStress )
  906. {
  907. OutputDebugString( buff );
  908. }
  909. } /* Msg */
  910. #endif