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

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