1058 lines
26 KiB
C
1058 lines
26 KiB
C
/*==========================================================================
|
|
*
|
|
* Copyright (c) 1995 - 1997 Microsoft Corporation. All Rights Reserved.
|
|
* Copyright (C) 1994-1995 ATI Technologies Inc. All Rights Reserved.
|
|
*
|
|
* File: winfox.c
|
|
* Content: Windows fox sample game
|
|
*
|
|
***************************************************************************/
|
|
#include "foxbear.h"
|
|
#include "rcids.h" // for FOX_ICON
|
|
|
|
LPDIRECTDRAWSURFACE lpFrontBuffer;
|
|
LPDIRECTDRAWSURFACE lpBackBuffer;
|
|
LPDIRECTDRAWCLIPPER lpClipper;
|
|
LPDIRECTDRAWSURFACE lpStretchBuffer;
|
|
LPDIRECTDRAWSURFACE lpFrameRate;
|
|
LPDIRECTDRAWSURFACE lpInfo;
|
|
LPDIRECTDRAWPALETTE lpPalette;
|
|
LPDIRECTDRAW lpDD;
|
|
SHORT lastInput = 0;
|
|
HWND hWndMain;
|
|
RECT rcWindow;
|
|
BOOL bShowFrameCount=TRUE;
|
|
BOOL bIsActive;
|
|
BOOL bPaused;
|
|
|
|
BOOL bStretch;
|
|
BOOL bFullscreen=TRUE;
|
|
BOOL bStress=FALSE; // just keep running if true
|
|
BOOL bHelp=FALSE; // help requested
|
|
RECT GameRect; // game rect
|
|
SIZE GameSize; // game is this size
|
|
SIZE GameMode; // display mode size
|
|
UINT GameBPP; // the bpp we want
|
|
DWORD dwColorKey; // our color key
|
|
DWORD AveFrameRate;
|
|
DWORD AveFrameRateCount;
|
|
BOOL bWantSound = TRUE;
|
|
|
|
|
|
#define OUR_APP_NAME "Win Fox Application"
|
|
|
|
#define ODS OutputDebugString
|
|
|
|
BOOL InitGame(void);
|
|
void ExitGame(void);
|
|
void initNumSurface(void);
|
|
|
|
|
|
/*
|
|
* PauseGame()
|
|
*/
|
|
void PauseGame()
|
|
{
|
|
Msg("**** PAUSE");
|
|
bPaused = TRUE;
|
|
InvalidateRect(hWndMain, NULL, TRUE);
|
|
}
|
|
|
|
/*
|
|
* UnPauseGame()
|
|
*/
|
|
void UnPauseGame()
|
|
{
|
|
if (GetForegroundWindow() == hWndMain)
|
|
{
|
|
Msg("**** UNPAUSE");
|
|
bPaused = FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* RestoreGame()
|
|
*/
|
|
BOOL RestoreGame()
|
|
{
|
|
if (lpFrontBuffer == NULL || IDirectDrawSurface_Restore(lpFrontBuffer) != DD_OK)
|
|
{
|
|
Msg("***** cant restore FrontBuffer");
|
|
return FALSE;
|
|
}
|
|
|
|
if (!bFullscreen)
|
|
{
|
|
if (lpBackBuffer == NULL || IDirectDrawSurface_Restore(lpBackBuffer) != DD_OK)
|
|
{
|
|
Msg("***** cant restore BackBuffer");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (lpStretchBuffer && IDirectDrawSurface_Restore(lpStretchBuffer) != DD_OK)
|
|
{
|
|
Msg("***** cant restore StretchBuffer");
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpFrameRate == NULL || lpInfo == NULL ||
|
|
IDirectDrawSurface_Restore(lpFrameRate) != DD_OK ||
|
|
IDirectDrawSurface_Restore(lpInfo) != DD_OK)
|
|
{
|
|
Msg("***** cant restore frame rate stuff");
|
|
return FALSE;
|
|
}
|
|
initNumSurface();
|
|
|
|
if (!gfxRestoreAll())
|
|
{
|
|
Msg("***** cant restore art");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* ProcessFox
|
|
*/
|
|
BOOL ProcessFox(SHORT sInput)
|
|
{
|
|
if ((lpFrontBuffer && IDirectDrawSurface_IsLost(lpFrontBuffer) == DDERR_SURFACELOST) ||
|
|
(lpBackBuffer && IDirectDrawSurface_IsLost(lpBackBuffer) == DDERR_SURFACELOST))
|
|
{
|
|
if (!RestoreGame())
|
|
{
|
|
PauseGame();
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
ProcessInput(sInput);
|
|
NewGameFrame();
|
|
return TRUE;
|
|
|
|
} /* ProcessFox */
|
|
|
|
static HFONT hFont;
|
|
|
|
DWORD dwFrameCount;
|
|
DWORD dwFrameTime;
|
|
DWORD dwFrames;
|
|
DWORD dwFramesLast;
|
|
SIZE sizeFPS;
|
|
SIZE sizeINFO;
|
|
int FrameRateX;
|
|
char szFPS[] = "FPS %02d";
|
|
char szINFO[] = "%dx%dx%d%s F6=mode F8=x2 ALT+ENTER=Window";
|
|
char szINFOW[] = "%dx%dx%d%s F6=mode F8=x2 ALT+ENTER=Fullscreen";
|
|
|
|
char szFrameRate[128];
|
|
char szInfo[128];
|
|
|
|
COLORREF InfoColor = RGB(0,152,245);
|
|
COLORREF FrameRateColor = RGB(255,255,0);
|
|
COLORREF BackColor = RGB(255,255,255);
|
|
|
|
/*
|
|
* initNumSurface
|
|
*/
|
|
void initNumSurface( void )
|
|
{
|
|
HDC hdc;
|
|
RECT rc;
|
|
int len;
|
|
|
|
dwFramesLast = 0;
|
|
|
|
len = wsprintf(szFrameRate, szFPS, 0, 0);
|
|
|
|
if( lpFrameRate && IDirectDrawSurface_GetDC(lpFrameRate, &hdc ) == DD_OK )
|
|
{
|
|
SelectObject(hdc, hFont);
|
|
SetTextColor(hdc, FrameRateColor);
|
|
SetBkColor(hdc, BackColor);
|
|
SetBkMode(hdc, OPAQUE);
|
|
SetRect(&rc, 0, 0, 10000, 10000);
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, szFrameRate, len, NULL);
|
|
GetTextExtentPoint(hdc, szFrameRate, 4, &sizeFPS);
|
|
FrameRateX = sizeFPS.cx;
|
|
GetTextExtentPoint(hdc, szFrameRate, len, &sizeFPS);
|
|
|
|
IDirectDrawSurface_ReleaseDC(lpFrameRate, hdc);
|
|
}
|
|
|
|
if (bFullscreen)
|
|
len = wsprintf(szInfo, szINFO,
|
|
GameSize.cx, GameSize.cy, GameBPP,bStretch ? " x2" : "");
|
|
else
|
|
len = wsprintf(szInfo, szINFOW,
|
|
GameSize.cx, GameSize.cy, GameBPP,bStretch ? " x2" : "");
|
|
|
|
if( lpInfo && IDirectDrawSurface_GetDC(lpInfo, &hdc ) == DD_OK )
|
|
{
|
|
SelectObject(hdc, hFont);
|
|
SetTextColor(hdc, InfoColor);
|
|
SetBkColor(hdc, BackColor);
|
|
SetBkMode(hdc, OPAQUE);
|
|
SetRect(&rc, 0, 0, 10000, 10000);
|
|
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, szInfo, len, NULL);
|
|
GetTextExtentPoint(hdc, szInfo, len, &sizeINFO);
|
|
|
|
IDirectDrawSurface_ReleaseDC(lpInfo, hdc);
|
|
}
|
|
|
|
} /* initNumSurface */
|
|
|
|
/*
|
|
* makeFontStuff
|
|
*/
|
|
static BOOL makeFontStuff( void )
|
|
{
|
|
DDCOLORKEY ddck;
|
|
HDC hdc;
|
|
|
|
if (hFont != NULL)
|
|
{
|
|
DeleteObject(hFont);
|
|
}
|
|
|
|
hFont = CreateFont(
|
|
GameSize.cx <= 512 ? 12 : 24,
|
|
0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
|
|
ANSI_CHARSET,
|
|
OUT_DEFAULT_PRECIS,
|
|
CLIP_DEFAULT_PRECIS,
|
|
NONANTIALIASED_QUALITY, // DEFAULT_QUALITY,
|
|
VARIABLE_PITCH,
|
|
"Arial" );
|
|
|
|
/*
|
|
* make a sample string so we can measure it with the current font.
|
|
*/
|
|
initNumSurface();
|
|
|
|
hdc = GetDC(NULL);
|
|
SelectObject(hdc, hFont);
|
|
GetTextExtentPoint(hdc, szFrameRate, lstrlen(szFrameRate), &sizeFPS);
|
|
GetTextExtentPoint(hdc, szInfo, lstrlen(szInfo), &sizeINFO);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
/*
|
|
* Create a surface to copy our bits to.
|
|
*/
|
|
lpFrameRate = DDCreateSurface(sizeFPS.cx, sizeFPS.cy, FALSE,TRUE);
|
|
lpInfo = DDCreateSurface(sizeINFO.cx, sizeINFO.cy, FALSE,TRUE);
|
|
|
|
if( lpFrameRate == NULL || lpInfo == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* now set the color key, we use a totaly different color than
|
|
* the rest of the app, just to be different so drivers dont always
|
|
* get white or black as the color key...
|
|
*
|
|
* dont forget when running on a dest colorkey device, we need
|
|
* to use the same color key as the rest of the app.
|
|
*/
|
|
if( bTransDest )
|
|
BackColor = RGB(255,255,255);
|
|
else
|
|
BackColor = RGB(128,64,255);
|
|
|
|
ddck.dwColorSpaceLowValue = DDColorMatch(lpInfo, BackColor);
|
|
ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
|
|
|
|
IDirectDrawSurface_SetColorKey( lpInfo, DDCKEY_SRCBLT, &ddck);
|
|
IDirectDrawSurface_SetColorKey( lpFrameRate, DDCKEY_SRCBLT, &ddck);
|
|
|
|
/*
|
|
* now draw the text for real
|
|
*/
|
|
initNumSurface();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* DisplayFrameRate
|
|
*/
|
|
void DisplayFrameRate( void )
|
|
{
|
|
DWORD time2;
|
|
char buff[256];
|
|
HDC hdc;
|
|
HRESULT ddrval;
|
|
RECT rc;
|
|
DWORD dw;
|
|
|
|
if( !bShowFrameCount )
|
|
{
|
|
return;
|
|
}
|
|
|
|
dwFrameCount++;
|
|
time2 = timeGetTime() - dwFrameTime;
|
|
if( time2 > 1000 )
|
|
{
|
|
dwFrames = (dwFrameCount*1000)/time2;
|
|
dwFrameTime = timeGetTime();
|
|
dwFrameCount = 0;
|
|
|
|
AveFrameRate += dwFrames;
|
|
AveFrameRateCount++;
|
|
}
|
|
|
|
if( dwFrames == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( dwFrames != dwFramesLast )
|
|
{
|
|
dwFramesLast = dwFrames;
|
|
|
|
if( IDirectDrawSurface_GetDC(lpFrameRate, &hdc ) == DD_OK )
|
|
{
|
|
buff[0] = (char)((dwFrames / 10) + '0');
|
|
buff[1] = (char)((dwFrames % 10) + '0');
|
|
|
|
SelectObject(hdc, hFont);
|
|
SetTextColor(hdc, FrameRateColor);
|
|
SetBkColor(hdc, BackColor);
|
|
TextOut(hdc, FrameRateX, 0, buff, 2);
|
|
|
|
IDirectDrawSurface_ReleaseDC(lpFrameRate, hdc);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* put the text on the back buffer.
|
|
*/
|
|
if (bTransDest)
|
|
dw = DDBLTFAST_DESTCOLORKEY | DDBLTFAST_WAIT;
|
|
else
|
|
dw = DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT;
|
|
|
|
SetRect(&rc, 0, 0, sizeFPS.cx, sizeFPS.cy);
|
|
ddrval = IDirectDrawSurface_BltFast(lpBackBuffer,
|
|
GameRect.left + (GameSize.cx - sizeFPS.cx)/2, GameRect.top + 20,
|
|
lpFrameRate, &rc, dw);
|
|
|
|
SetRect(&rc, 0, 0, sizeINFO.cx, sizeINFO.cy);
|
|
ddrval = IDirectDrawSurface_BltFast(lpBackBuffer,
|
|
GameRect.left + 10, GameRect.bottom - sizeINFO.cy - 10,
|
|
lpInfo, &rc, dw);
|
|
|
|
} /* DisplayFrameRate */
|
|
|
|
/*
|
|
* MainWndProc
|
|
*
|
|
* Callback for all Windows messages
|
|
*/
|
|
long FAR PASCAL MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc;
|
|
int i;
|
|
|
|
switch( message )
|
|
{
|
|
case WM_SIZE:
|
|
case WM_MOVE:
|
|
if (IsIconic(hWnd))
|
|
{
|
|
Msg("FoxBear is minimized, pausing");
|
|
PauseGame();
|
|
}
|
|
|
|
if (bFullscreen)
|
|
{
|
|
SetRect(&rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
|
|
}
|
|
else
|
|
{
|
|
GetClientRect(hWnd, &rcWindow);
|
|
ClientToScreen(hWnd, (LPPOINT)&rcWindow);
|
|
ClientToScreen(hWnd, (LPPOINT)&rcWindow+1);
|
|
}
|
|
Msg("WINDOW RECT: [%d,%d,%d,%d]", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom);
|
|
break;
|
|
|
|
case WM_ACTIVATEAPP:
|
|
bIsActive = (BOOL)wParam && GetForegroundWindow() == hWnd;
|
|
|
|
if (bIsActive)
|
|
Msg("FoxBear is active");
|
|
else
|
|
Msg("FoxBear is not active");
|
|
|
|
//
|
|
// while we were not-active something bad happened that caused us
|
|
// to pause, like a surface restore failing or we got a palette
|
|
// changed, now that we are active try to fix things
|
|
//
|
|
if (bPaused && bIsActive)
|
|
{
|
|
if (RestoreGame())
|
|
{
|
|
UnPauseGame();
|
|
}
|
|
else
|
|
{
|
|
if (GetForegroundWindow() == hWnd)
|
|
{
|
|
//
|
|
// we are unable to restore, this can happen when
|
|
// the screen resolution or bitdepth has changed
|
|
// we just reload all the art again and re-create
|
|
// the front and back buffers. this is a little
|
|
// overkill we could handle a screen res change by
|
|
// just recreating the front and back buffers we dont
|
|
// need to redo the art, but this is way easier.
|
|
//
|
|
if (InitGame())
|
|
{
|
|
UnPauseGame();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_QUERYNEWPALETTE:
|
|
//
|
|
// we are getting the palette focus, select our palette
|
|
//
|
|
if (!bFullscreen && lpPalette && lpFrontBuffer)
|
|
{
|
|
HRESULT ddrval;
|
|
|
|
ddrval = IDirectDrawSurface_SetPalette(lpFrontBuffer,lpPalette);
|
|
if( ddrval == DDERR_SURFACELOST )
|
|
{
|
|
IDirectDrawSurface_Restore( lpFrontBuffer );
|
|
|
|
ddrval= IDirectDrawSurface_SetPalette(lpFrontBuffer,lpPalette);
|
|
if( ddrval == DDERR_SURFACELOST )
|
|
{
|
|
Msg(" Failed to restore palette after second try");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Restore normal title if palette is ours
|
|
//
|
|
|
|
if( ddrval == DD_OK )
|
|
{
|
|
SetWindowText( hWnd, OUR_APP_NAME );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_PALETTECHANGED:
|
|
//
|
|
// if another app changed the palette we dont have full control
|
|
// of the palette. NOTE this only applies for FoxBear in a window
|
|
// when we are fullscreen we get all the palette all of the time.
|
|
//
|
|
if ((HWND)wParam != hWnd)
|
|
{
|
|
if( !bFullscreen )
|
|
{
|
|
if( !bStress )
|
|
{
|
|
Msg("***** PALETTE CHANGED, PAUSING GAME");
|
|
PauseGame();
|
|
}
|
|
else
|
|
{
|
|
Msg("Lost palette but continuing");
|
|
SetWindowText( hWnd, OUR_APP_NAME
|
|
" - palette changed COLORS PROBABLY WRONG" );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_DISPLAYCHANGE:
|
|
break;
|
|
|
|
case WM_CREATE:
|
|
break;
|
|
|
|
case WM_SETCURSOR:
|
|
if (bFullscreen && bIsActive)
|
|
{
|
|
SetCursor(NULL);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_SYSKEYUP:
|
|
switch( wParam )
|
|
{
|
|
// handle ALT+ENTER (fullscreen)
|
|
case VK_RETURN:
|
|
bFullscreen = !bFullscreen;
|
|
ExitGame();
|
|
DDDisable(TRUE); // destroy DirectDraw object
|
|
InitGame();
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
switch( wParam )
|
|
{
|
|
case VK_NUMPAD5:
|
|
lastInput=KEY_STOP;
|
|
break;
|
|
case VK_DOWN:
|
|
case VK_NUMPAD2:
|
|
lastInput=KEY_DOWN;
|
|
break;
|
|
case VK_LEFT:
|
|
case VK_NUMPAD4:
|
|
lastInput=KEY_LEFT;
|
|
break;
|
|
case VK_RIGHT:
|
|
case VK_NUMPAD6:
|
|
lastInput=KEY_RIGHT;
|
|
break;
|
|
case VK_UP:
|
|
case VK_NUMPAD8:
|
|
lastInput=KEY_UP;
|
|
break;
|
|
case VK_HOME:
|
|
case VK_NUMPAD7:
|
|
lastInput=KEY_JUMP;
|
|
break;
|
|
case VK_NUMPAD3:
|
|
lastInput=KEY_THROW;
|
|
break;
|
|
case VK_F5:
|
|
bShowFrameCount = !bShowFrameCount;
|
|
if( bShowFrameCount )
|
|
{
|
|
dwFrameCount = 0;
|
|
dwFrameTime = timeGetTime();
|
|
}
|
|
break;
|
|
|
|
case VK_F6:
|
|
//
|
|
// find our current mode in the mode list
|
|
//
|
|
if(bFullscreen)
|
|
{
|
|
for (i=0; i<NumModes; i++)
|
|
{
|
|
if (ModeList[i].bpp == (int)GameBPP &&
|
|
ModeList[i].w == GameSize.cx &&
|
|
ModeList[i].h == GameSize.cy)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}else
|
|
{
|
|
for (i=0; i<NumModes; i++)
|
|
{
|
|
if (ModeList[i].w == GameSize.cx &&
|
|
ModeList[i].h == GameSize.cy)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// now step to the next mode, wrapping to the first one.
|
|
//
|
|
if (++i >= NumModes)
|
|
i = 0;
|
|
Msg("ModeList %d %d",i,NumModes);
|
|
GameMode.cx = ModeList[i].w;
|
|
GameMode.cy = ModeList[i].h;
|
|
GameBPP = ModeList[i].bpp;
|
|
bStretch = FALSE;
|
|
InitGame();
|
|
break;
|
|
|
|
case VK_F7:
|
|
GameBPP = GameBPP == 8 ? 16 : 8;
|
|
InitGame();
|
|
break;
|
|
|
|
case VK_F8:
|
|
if (bFullscreen)
|
|
{
|
|
bStretch = !bStretch;
|
|
InitGame();
|
|
}
|
|
else
|
|
{
|
|
RECT rc;
|
|
|
|
GetClientRect(hWnd, &rc);
|
|
|
|
bStretch = (rc.right != GameSize.cx) ||
|
|
(rc.bottom != GameSize.cy);
|
|
|
|
if (bStretch = !bStretch)
|
|
SetRect(&rc, 0, 0, GameMode.cx*2, GameMode.cy*2);
|
|
else
|
|
SetRect(&rc, 0, 0, GameMode.cx, GameMode.cy);
|
|
|
|
AdjustWindowRectEx(&rc,
|
|
GetWindowStyle(hWnd),
|
|
GetMenu(hWnd) != NULL,
|
|
GetWindowExStyle(hWnd));
|
|
|
|
SetWindowPos(hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
|
|
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
break;
|
|
|
|
case VK_F4:
|
|
// treat F4 like ALT+ENTER (fullscreen)
|
|
PostMessage(hWnd, WM_SYSKEYUP, VK_RETURN, 0);
|
|
break;
|
|
|
|
case VK_F3:
|
|
bPaused = !bPaused;
|
|
break;
|
|
|
|
case VK_ESCAPE:
|
|
case VK_F12:
|
|
PostMessage(hWnd, WM_CLOSE, 0, 0);
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
hdc = BeginPaint( hWnd, &ps );
|
|
if (bPaused)
|
|
{
|
|
char *sz = "Game is paused, this is not a bug.";
|
|
TextOut(ps.hdc, 0, 0, sz, lstrlen(sz));
|
|
}
|
|
EndPaint( hWnd, &ps );
|
|
return 1;
|
|
|
|
case WM_DESTROY:
|
|
hWndMain = NULL;
|
|
lastInput=0;
|
|
DestroyGame(); // end of game
|
|
DDDisable(TRUE); // destroy DirectDraw object
|
|
PostQuitMessage( 0 );
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
|
|
} /* MainWndProc */
|
|
|
|
/*
|
|
* initApplication
|
|
*
|
|
* Do that Windows initialization stuff...
|
|
*/
|
|
static BOOL initApplication( HINSTANCE hInstance, int nCmdShow )
|
|
{
|
|
WNDCLASS wc;
|
|
BOOL rc;
|
|
|
|
wc.style = CS_DBLCLKS;
|
|
wc.lpfnWndProc = MainWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = hInstance;
|
|
wc.hIcon = LoadIcon( hInstance, MAKEINTATOM(FOX_ICON));
|
|
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
|
|
wc.hbrBackground = GetStockObject(BLACK_BRUSH);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = "WinFoxClass";
|
|
rc = RegisterClass( &wc );
|
|
if( !rc )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
hWndMain = CreateWindowEx(
|
|
WS_EX_APPWINDOW,
|
|
"WinFoxClass",
|
|
OUR_APP_NAME,
|
|
WS_VISIBLE | // so we dont have to call ShowWindow
|
|
WS_SYSMENU | // so we get a icon in in our tray button
|
|
WS_POPUP,
|
|
0,
|
|
0,
|
|
GetSystemMetrics(SM_CXSCREEN),
|
|
GetSystemMetrics(SM_CYSCREEN),
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL );
|
|
|
|
if( !hWndMain )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UpdateWindow( hWndMain );
|
|
SetFocus( hWndMain );
|
|
|
|
return TRUE;
|
|
|
|
} /* initApplication */
|
|
|
|
/*
|
|
* ExitGame
|
|
*
|
|
* Exiting current game, clean up
|
|
*/
|
|
void ExitGame( void )
|
|
{
|
|
if( lpFrameRate )
|
|
{
|
|
IDirectDrawSurface_Release(lpFrameRate);
|
|
lpFrameRate = NULL;
|
|
}
|
|
|
|
if( lpInfo )
|
|
{
|
|
IDirectDrawSurface_Release(lpInfo);
|
|
lpInfo = NULL;
|
|
}
|
|
|
|
if( lpPalette )
|
|
{
|
|
IDirectDrawSurface_Release(lpPalette);
|
|
lpPalette = NULL;
|
|
}
|
|
|
|
DestroyGame();
|
|
|
|
} /* ExitGame */
|
|
|
|
/*
|
|
* InitGame
|
|
*
|
|
* Initializing current game
|
|
*/
|
|
BOOL InitGame( void )
|
|
{
|
|
ExitGame();
|
|
|
|
GameSize = GameMode;
|
|
|
|
/*
|
|
* initialize sound
|
|
*/
|
|
InitSound( hWndMain );
|
|
|
|
/*
|
|
* init DirectDraw, set mode, ...
|
|
* NOTE GameMode might be set to 640x480 if we cant get the asked for mode.
|
|
*/
|
|
if( !PreInitializeGame() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (bStretch && bFullscreen)
|
|
{
|
|
GameSize.cx = GameMode.cx / 2;
|
|
GameSize.cy = GameMode.cy / 2;
|
|
GameRect.left = GameMode.cx - GameSize.cx;
|
|
GameRect.top = GameMode.cy - GameSize.cy;
|
|
GameRect.right = GameMode.cx;
|
|
GameRect.bottom = GameMode.cy;
|
|
|
|
if (lpStretchBuffer)
|
|
Msg("Stretching using a system-memory stretch buffer");
|
|
else
|
|
Msg("Stretching using a VRAM->VRAM blt");
|
|
}
|
|
else
|
|
{
|
|
GameRect.left = (GameMode.cx - GameSize.cx) / 2;
|
|
GameRect.top = (GameMode.cy - GameSize.cy) / 2;
|
|
GameRect.right = GameRect.left + GameSize.cx;
|
|
GameRect.bottom = GameRect.top + GameSize.cy;
|
|
}
|
|
|
|
/*
|
|
* setup our palette
|
|
*/
|
|
if( GameBPP == 8 )
|
|
{
|
|
lpPalette = ReadPalFile( NULL ); // create a 332 palette
|
|
|
|
if( lpPalette == NULL )
|
|
{
|
|
Msg( "Palette create failed" );
|
|
return FALSE;
|
|
}
|
|
|
|
IDirectDrawSurface_SetPalette( lpFrontBuffer, lpPalette );
|
|
}
|
|
|
|
/*
|
|
* load all the art and things.
|
|
*/
|
|
if( !InitializeGame() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* init our code to draw the FPS
|
|
*/
|
|
makeFontStuff();
|
|
|
|
/*
|
|
* spew some stats
|
|
*/
|
|
{
|
|
DDCAPS ddcaps;
|
|
ddcaps.dwSize = sizeof( ddcaps );
|
|
IDirectDraw_GetCaps( lpDD, &ddcaps, NULL );
|
|
Msg( "Total=%ld, Free VRAM=%ld", ddcaps.dwVidMemTotal, ddcaps.dwVidMemFree );
|
|
Msg( "Used = %ld", ddcaps.dwVidMemTotal- ddcaps.dwVidMemFree );
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* InitGame */
|
|
|
|
#define IS_NUM(c) ((c) >= '0' && (c) <= '9')
|
|
#define IS_SPACE(c) ((c) == ' ' || (c) == '\r' || (c) == '\n' || (c) == '\t' || (c) == 'x')
|
|
|
|
int getint(char**p, int def)
|
|
{
|
|
int i=0;
|
|
|
|
while (IS_SPACE(**p))
|
|
(*p)++;
|
|
|
|
if (!IS_NUM(**p))
|
|
return def;
|
|
|
|
while (IS_NUM(**p))
|
|
i = i*10 + *(*p)++ - '0';
|
|
|
|
while (IS_SPACE(**p))
|
|
(*p)++;
|
|
|
|
return i;
|
|
}
|
|
|
|
/*
|
|
* WinMain
|
|
*/
|
|
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
|
|
int nCmdShow )
|
|
{
|
|
MSG msg;
|
|
|
|
while( lpCmdLine[0] == '-' )
|
|
{
|
|
int iMoviePos = 0;
|
|
BOOL bDone = FALSE;
|
|
lpCmdLine++;
|
|
|
|
switch (*lpCmdLine++)
|
|
{
|
|
case 'c':
|
|
bCamera = TRUE;
|
|
break;
|
|
|
|
case 'm':
|
|
bMovie = TRUE;
|
|
for (;!bDone;) {
|
|
switch (*lpCmdLine) {
|
|
case ' ':
|
|
case 0:
|
|
case '-':
|
|
case '\n':
|
|
case '\r':
|
|
bDone = TRUE;
|
|
break;
|
|
default:
|
|
wszMovie[iMoviePos++] = (unsigned char)*lpCmdLine++;
|
|
break;
|
|
}
|
|
}
|
|
wszMovie[iMoviePos] = 0;
|
|
break;
|
|
case 'e':
|
|
bUseEmulation = TRUE;
|
|
break;
|
|
case 'w':
|
|
bFullscreen = FALSE;
|
|
break;
|
|
case 'f':
|
|
bFullscreen = TRUE;
|
|
break;
|
|
case '1':
|
|
CmdLineBufferCount = 1;
|
|
break;
|
|
case '2':
|
|
case 'd':
|
|
CmdLineBufferCount = 2;
|
|
break;
|
|
case '3':
|
|
CmdLineBufferCount = 3;
|
|
break;
|
|
case 's':
|
|
bStretch = TRUE;
|
|
break;
|
|
case 'S':
|
|
bWantSound = FALSE;
|
|
break;
|
|
case 'x':
|
|
bStress= TRUE;
|
|
break;
|
|
case '?':
|
|
bHelp= TRUE;
|
|
bFullscreen= FALSE; // give help in windowed mode
|
|
break;
|
|
}
|
|
|
|
while( IS_SPACE(*lpCmdLine) )
|
|
{
|
|
lpCmdLine++;
|
|
}
|
|
}
|
|
|
|
GameMode.cx = getint(&lpCmdLine, 640);
|
|
GameMode.cy = getint(&lpCmdLine, 480);
|
|
GameBPP = getint(&lpCmdLine, 8);
|
|
|
|
/*
|
|
* create window and other windows things
|
|
*/
|
|
if( !initApplication(hInstance, nCmdShow) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Give user help if asked for
|
|
*
|
|
* This is ugly for now because the whole screen is black
|
|
* except for the popup box. This could be fixed with some
|
|
* work to get the window size right when it was created instead
|
|
* of delaying that work. see ddraw.c
|
|
*
|
|
*/
|
|
|
|
if( bHelp )
|
|
{
|
|
MessageBox(hWndMain,
|
|
"F12 - Quit\n"
|
|
"NUMPAD 2 - crouch\n"
|
|
"NUMPAD 3 - apple\n"
|
|
"NUMPAD 4 - right\n"
|
|
"NUMPAD 5 - stop\n"
|
|
"NUMPAD 6 - left\n"
|
|
"NUMPAD 7 - jump\n"
|
|
"\n"
|
|
"Command line parameters\n"
|
|
"\n"
|
|
"-e Use emulator\n"
|
|
"-S No Sound\n"
|
|
"-1 No backbuffer\n"
|
|
"-2 One backbuffer\n"
|
|
"-4 Three backbuffers\n"
|
|
"-s Use stretch\n"
|
|
"-x Demo or stress mode\n"
|
|
"-mfoo.bar Movie name\n"
|
|
"-c Overlay camera input\n",
|
|
OUR_APP_NAME, MB_OK );
|
|
}
|
|
|
|
/*
|
|
* initialize for game play
|
|
*/
|
|
if( !InitGame() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
dwFrameTime = timeGetTime();
|
|
|
|
while( 1 )
|
|
{
|
|
if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE))
|
|
{
|
|
if (!GetMessage( &msg, NULL, 0, 0))
|
|
{
|
|
break;
|
|
}
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
else if (!bPaused && (bIsActive || !bFullscreen))
|
|
{
|
|
ProcessFox(lastInput);
|
|
lastInput=0;
|
|
}
|
|
else
|
|
{
|
|
WaitMessage();
|
|
}
|
|
}
|
|
|
|
if (AveFrameRateCount)
|
|
{
|
|
AveFrameRate = AveFrameRate / AveFrameRateCount;
|
|
Msg("Average frame rate: %d", AveFrameRate);
|
|
}
|
|
|
|
return msg.wParam;
|
|
|
|
} /* WinMain */
|
|
|
|
#ifdef DEBUG
|
|
|
|
/*
|
|
* Msg
|
|
*/
|
|
void __cdecl Msg( LPSTR fmt, ... )
|
|
{
|
|
char buff[256];
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
|
|
|
//
|
|
// format message with header
|
|
//
|
|
|
|
lstrcpy( buff, "FOXBEAR:" );
|
|
wvsprintf( &buff[lstrlen(buff)], fmt, va );
|
|
lstrcat( buff, "\r\n" );
|
|
|
|
//
|
|
// To the debugger unless we need to be quiet
|
|
//
|
|
|
|
if( !bStress )
|
|
{
|
|
OutputDebugString( buff );
|
|
}
|
|
|
|
} /* Msg */
|
|
|
|
#endif
|