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

Windows编程

开发平台:

Visual C++

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