845 lines
21 KiB
C
845 lines
21 KiB
C
/*==========================================================================
|
|
*
|
|
* Copyright (c) 1995 - 1997 Microsoft Corporation. All Rights Reserved.
|
|
* Copyright (C) 1994-1995 ATI Technologies Inc. All Rights Reserved.
|
|
*
|
|
* File: ddraw.c
|
|
* Content: Misc. Direct Draw access routines
|
|
*
|
|
***************************************************************************/
|
|
#include "foxbear.h"
|
|
|
|
BOOL bUseEmulation;
|
|
BOOL bUseSysMem;
|
|
int nBufferCount;
|
|
int CmdLineBufferCount;
|
|
BOOL bTransDest;
|
|
BOOL bColorFill;
|
|
|
|
HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context);
|
|
|
|
/*
|
|
* DDEnable
|
|
*/
|
|
BOOL DDEnable( void )
|
|
{
|
|
LPDIRECTDRAW lpdd;
|
|
DDCAPS ddcaps;
|
|
HRESULT ddrval;
|
|
BOOL use_dest;
|
|
|
|
nBufferCount = GetProfileInt( "FoxBear", "buffers", CmdLineBufferCount);
|
|
bUseEmulation = GetProfileInt( "FoxBear", "use_emulation", bUseEmulation);
|
|
bUseSysMem = GetProfileInt( "FoxBear", "sysmem", 0);
|
|
use_dest = GetProfileInt( "FoxBear", "use_dest", 0 );
|
|
|
|
if (lpDD == NULL)
|
|
{
|
|
if( bUseEmulation )
|
|
{
|
|
ddrval = DirectDrawCreate( (LPVOID) DDCREATE_EMULATIONONLY, &lpdd, NULL );
|
|
}
|
|
else
|
|
{
|
|
ddrval = DirectDrawCreate( NULL, &lpdd, NULL );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpdd = lpDD;
|
|
ddrval = DD_OK;
|
|
}
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("DirectDrawCreate failed err=%d", ddrval);
|
|
goto error;
|
|
}
|
|
|
|
/*
|
|
* grab exclusive mode if we are going to run as fullscreen
|
|
* otherwise grab normal mode.
|
|
*/
|
|
if (lpDD == NULL)
|
|
{
|
|
NumModes = 0;
|
|
|
|
if (bFullscreen)
|
|
{
|
|
ddrval = IDirectDraw_SetCooperativeLevel( lpdd, hWndMain,
|
|
DDSCL_ALLOWMODEX |
|
|
DDSCL_EXCLUSIVE |
|
|
DDSCL_FULLSCREEN );
|
|
|
|
// in fullscreen mode, enumeratte the available modes
|
|
IDirectDraw_EnumDisplayModes(lpdd, 0, NULL, 0, EnumDisplayModesCallback);
|
|
}
|
|
else
|
|
{
|
|
ddrval = IDirectDraw_SetCooperativeLevel( lpdd, hWndMain,
|
|
DDSCL_NORMAL );
|
|
|
|
// in normal windowed mode, just add some "stock" window
|
|
// sizes
|
|
|
|
ModeList[NumModes].w = 320;
|
|
ModeList[NumModes].h = 200;
|
|
NumModes++;
|
|
|
|
ModeList[NumModes].w = 320;
|
|
ModeList[NumModes].h = 240;
|
|
NumModes++;
|
|
|
|
ModeList[NumModes].w = 512;
|
|
ModeList[NumModes].h = 384;
|
|
NumModes++;
|
|
|
|
ModeList[NumModes].w = 640;
|
|
ModeList[NumModes].h = 400;
|
|
NumModes++;
|
|
|
|
ModeList[NumModes].w = 640;
|
|
ModeList[NumModes].h = 480;
|
|
NumModes++;
|
|
}
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("SetCooperativeLevel failed err=%d", ddrval);
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
if (bFullscreen)
|
|
{
|
|
Msg("SetDisplayMode %d %d %d",GameMode.cx,GameMode.cy, GameBPP);
|
|
ddrval = IDirectDraw_SetDisplayMode( lpdd,
|
|
GameMode.cx, GameMode.cy, GameBPP);
|
|
|
|
if (ddrval != DD_OK && (GameMode.cx != 640 || GameMode.cy != 480))
|
|
{
|
|
Msg( "cant set mode trying 640x480" );
|
|
|
|
GameMode.cx = 640;
|
|
GameMode.cy = 480;
|
|
GameSize = GameMode;
|
|
|
|
ddrval = IDirectDraw_SetDisplayMode( lpdd,
|
|
GameMode.cx, GameMode.cy, GameBPP);
|
|
}
|
|
|
|
if (ddrval != DD_OK && GameBPP != 8)
|
|
{
|
|
Msg( "cant set mode trying 640x480x8" );
|
|
|
|
GameBPP = 8;
|
|
|
|
ddrval = IDirectDraw_SetDisplayMode( lpdd,
|
|
GameMode.cx, GameMode.cy, GameBPP);
|
|
}
|
|
|
|
if (ddrval != DD_OK && GameBPP != 16)
|
|
{
|
|
Msg( "cant set mode trying 640x480x16" );
|
|
|
|
GameBPP = 16;
|
|
|
|
ddrval = IDirectDraw_SetDisplayMode( lpdd,
|
|
GameMode.cx, GameMode.cy, GameBPP);
|
|
}
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("SetMode failed err=%d", ddrval);
|
|
goto error;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RECT rcWork;
|
|
RECT rc;
|
|
HDC hdc;
|
|
DWORD dwStyle;
|
|
|
|
//
|
|
// when in rome (I mean when in windows) we should use the
|
|
// current mode
|
|
//
|
|
hdc = GetDC(NULL);
|
|
GameBPP = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
//
|
|
// if we are still a WS_POPUP window we should convert to a
|
|
// normal app window so we look like a windows app.
|
|
//
|
|
dwStyle = GetWindowStyle(hWndMain);
|
|
dwStyle &= ~WS_POPUP;
|
|
dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
|
|
SetWindowLong(hWndMain, GWL_STYLE, dwStyle);
|
|
|
|
if (bStretch)
|
|
SetRect(&rc, 0, 0, GameMode.cx*2, GameMode.cy*2);
|
|
else
|
|
SetRect(&rc, 0, 0, GameMode.cx, GameMode.cy);
|
|
|
|
AdjustWindowRectEx(&rc,
|
|
GetWindowStyle(hWndMain),
|
|
GetMenu(hWndMain) != NULL,
|
|
GetWindowExStyle(hWndMain));
|
|
|
|
SetWindowPos(hWndMain, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
|
|
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
SetWindowPos(hWndMain, HWND_NOTOPMOST, 0, 0, 0, 0,
|
|
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
|
|
|
|
//
|
|
// make sure our window does not hang outside of the work area
|
|
// this will make people who have the tray on the top or left
|
|
// happy.
|
|
//
|
|
SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0);
|
|
GetWindowRect(hWndMain, &rc);
|
|
if (rc.left < rcWork.left) rc.left = rcWork.left;
|
|
if (rc.top < rcWork.top) rc.top = rcWork.top;
|
|
SetWindowPos(hWndMain, NULL, rc.left, rc.top, 0, 0,
|
|
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
/*
|
|
* check capabilites
|
|
*/
|
|
ddcaps.dwSize = sizeof( ddcaps );
|
|
ddrval = IDirectDraw_GetCaps( lpdd, &ddcaps, NULL );
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("GetCaps failed err=%d", ddrval);
|
|
goto error;
|
|
}
|
|
|
|
if( ddcaps.dwCaps & DDCAPS_NOHARDWARE )
|
|
{
|
|
Msg( "No hardware support at all" );
|
|
}
|
|
|
|
if( ddcaps.dwCaps & DDCAPS_BLTCOLORFILL )
|
|
{
|
|
bColorFill = TRUE;
|
|
Msg( "Device supports color fill" );
|
|
}
|
|
else
|
|
{
|
|
bColorFill = FALSE;
|
|
Msg( "Device does not support color fill" );
|
|
}
|
|
|
|
/*
|
|
* default to double buffered on 1mb, triple buffered
|
|
* on > 1mb
|
|
*/
|
|
if (nBufferCount == 0)
|
|
{
|
|
if( ddcaps.dwVidMemTotal <= 1024L*1024L*(GameBPP/8) ||
|
|
GameMode.cx > 640 )
|
|
{
|
|
Msg("double buffering (not enough memory)");
|
|
nBufferCount = 2;
|
|
}
|
|
else
|
|
{
|
|
Msg("triple buffering");
|
|
nBufferCount = 3;
|
|
}
|
|
}
|
|
|
|
if( ddcaps.dwCaps & DDCAPS_COLORKEY )
|
|
{
|
|
if( ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT )
|
|
{
|
|
Msg( "Can do Src colorkey in hardware" );
|
|
}
|
|
|
|
if( ddcaps.dwCKeyCaps & DDCKEYCAPS_DESTBLT )
|
|
{
|
|
Msg( "Can do Dest colorkey in hardware" );
|
|
if( use_dest || !(ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) )
|
|
{
|
|
/*
|
|
* since direct draw doesn't support
|
|
* destination color key in emulation, only
|
|
* use it if there is enough vram ...
|
|
*/
|
|
if( ddcaps.dwVidMemTotal >= 2 * 1024L*1024L*(GameBPP/8) )
|
|
{
|
|
Msg( "Using destination color key" );
|
|
bTransDest = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Msg( "Can't do color key in hardware!" );
|
|
}
|
|
|
|
lpDD = lpdd;
|
|
return TRUE;
|
|
|
|
error:
|
|
return FALSE;
|
|
|
|
} /* DDEnable */
|
|
|
|
/*
|
|
* DDDisable
|
|
*/
|
|
BOOL DDDisable( BOOL fFinal )
|
|
{
|
|
if( lpClipper )
|
|
{
|
|
IDirectDrawClipper_Release(lpClipper);
|
|
lpClipper = NULL;
|
|
}
|
|
|
|
if( lpBackBuffer )
|
|
{
|
|
IDirectDrawSurface_Release(lpBackBuffer);
|
|
lpBackBuffer = NULL;
|
|
}
|
|
|
|
if( lpFrontBuffer )
|
|
{
|
|
IDirectDrawSurface_Release(lpFrontBuffer);
|
|
lpFrontBuffer = NULL;
|
|
}
|
|
|
|
if( lpStretchBuffer )
|
|
{
|
|
IDirectDrawSurface_Release(lpStretchBuffer);
|
|
lpStretchBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// fFinal is TRUE when the app is exiting, FALSE if we are
|
|
// just seting a new game size..
|
|
//
|
|
if ( fFinal )
|
|
{
|
|
if( lpDD != NULL )
|
|
{
|
|
IDirectDraw_Release( lpDD );
|
|
lpDD = NULL;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* DDClear
|
|
*
|
|
* clear the front buffer and all backbuffers.
|
|
*/
|
|
BOOL DDClear( void )
|
|
{
|
|
DDBLTFX ddbltfx;
|
|
int i;
|
|
HRESULT ddrval;
|
|
|
|
UpdateWindow(hWndMain);
|
|
|
|
ddbltfx.dwSize = sizeof( ddbltfx );
|
|
ddbltfx.dwFillColor = DDColorMatch(lpBackBuffer, RGB(0, 0, 200));
|
|
|
|
if (bFullscreen)
|
|
{
|
|
/*
|
|
* do it for all buffers, we either have 1 or 2 back buffers
|
|
* make sure we get them all, 4 is plenty!
|
|
*/
|
|
for( i=0; i<4; i++ )
|
|
{
|
|
ddrval = IDirectDrawSurface_Blt(
|
|
lpBackBuffer, // dest surface
|
|
NULL, // dest rect
|
|
NULL, // src surface
|
|
NULL, // src rect
|
|
DDBLT_COLORFILL | DDBLT_WAIT,
|
|
&ddbltfx);
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("Fill failed ddrval =0x%08lX", ddrval);
|
|
return FALSE;
|
|
}
|
|
|
|
ddrval = IDirectDrawSurface_Flip(lpFrontBuffer, NULL, DDFLIP_WAIT);
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("Flip failed ddrval =0x%08lX", ddrval );
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ddrval = IDirectDrawSurface_Blt(
|
|
lpFrontBuffer, // dest surface
|
|
&rcWindow, // dest rect
|
|
NULL, // src surface
|
|
NULL, // src rect
|
|
DDBLT_COLORFILL | DDBLT_WAIT,
|
|
&ddbltfx);
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("Fill failed ddrval =0x%08lX", ddrval);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* DDClear */
|
|
|
|
/*
|
|
* DDCreateFlippingSurface
|
|
*
|
|
* create a FrontBuffer and a BackBuffer(s)
|
|
*
|
|
*/
|
|
BOOL DDCreateFlippingSurface( void )
|
|
{
|
|
DDPIXELFORMAT ddpf;
|
|
DDSURFACEDESC ddsd;
|
|
HRESULT ddrval;
|
|
DDSCAPS ddscaps;
|
|
DDCAPS ddcaps;
|
|
|
|
ddcaps.dwSize = sizeof( ddcaps );
|
|
|
|
if( IDirectDraw_GetCaps( lpDD, &ddcaps, NULL ) != DD_OK )
|
|
return FALSE;
|
|
|
|
/*
|
|
* fill in surface desc:
|
|
* want a primary surface with 2 back buffers
|
|
*/
|
|
ZeroMemory( &ddsd, sizeof( ddsd ) );
|
|
ddsd.dwSize = sizeof( ddsd );
|
|
|
|
if (bFullscreen && nBufferCount > 1)
|
|
{
|
|
//
|
|
// fullscreen case, create a primary (ie front) and
|
|
// either 1 or 2 back buffers
|
|
//
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
|
ddsd.dwBackBufferCount = nBufferCount-1;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
|
|
DDSCAPS_FLIP | DDSCAPS_COMPLEX;
|
|
|
|
OutputDebugString("Creating multiple backbuffer primary\n\r");
|
|
ddrval = IDirectDraw_CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg( "CreateSurface FAILED! %08lx", ddrval );
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* go find the back buffer
|
|
*/
|
|
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
|
|
ddrval = IDirectDrawSurface_GetAttachedSurface(
|
|
lpFrontBuffer,
|
|
&ddscaps,
|
|
&lpBackBuffer );
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg( "GetAttachedSurface failed! err=%d",ddrval );
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* if we are stretching create a buffer to stretch into
|
|
*
|
|
* NOTE we always make this buffer in system memory because
|
|
* we render to the backbuffer (in VRAM) at half the size
|
|
* now we need to stretch into the backbuffer. we could just
|
|
* do a VRAM->VRAM stretch, but this is REAL REAL REAL slow on
|
|
* some cards (banked cards..)
|
|
*/
|
|
if( bStretch && (ddcaps.dwCaps & DDCAPS_BANKSWITCHED) )
|
|
{
|
|
Msg( "On bank switched hardware, creating stretch buffer" );
|
|
lpStretchBuffer = DDCreateSurface( GameSize.cx, GameSize.cy,
|
|
TRUE, FALSE );
|
|
}
|
|
}
|
|
else if (bFullscreen && nBufferCount == 1)
|
|
{
|
|
ddsd.dwFlags = DDSD_CAPS;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
|
|
OutputDebugString("Creating no backbuffer primary\n\r");
|
|
ddrval = IDirectDraw_CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg( "CreateSurface FAILED! %08lx", ddrval );
|
|
return FALSE;
|
|
}
|
|
|
|
IDirectDrawSurface_AddRef(lpFrontBuffer);
|
|
lpBackBuffer = lpFrontBuffer;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// window case, create the primary surface
|
|
// and create a backbuffer in offscreen memory.
|
|
//
|
|
ddsd.dwFlags = DDSD_CAPS;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
|
|
ddrval = IDirectDraw_CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg( "CreateSurface FAILED! %08lx", ddrval );
|
|
return FALSE;
|
|
}
|
|
|
|
lpBackBuffer = DDCreateSurface( GameSize.cx, GameSize.cy, FALSE, FALSE );
|
|
|
|
if( lpBackBuffer == NULL )
|
|
{
|
|
Msg( "Cant create the backbuffer" );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// now create a DirectDrawClipper object.
|
|
//
|
|
ddrval = IDirectDraw_CreateClipper(lpDD, 0, &lpClipper, NULL);
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("Cant create clipper");
|
|
return FALSE;
|
|
}
|
|
|
|
ddrval = IDirectDrawClipper_SetHWnd(lpClipper, 0, hWndMain);
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("Cant set clipper window handle");
|
|
return FALSE;
|
|
}
|
|
|
|
ddrval = IDirectDrawSurface_SetClipper(lpFrontBuffer, lpClipper);
|
|
|
|
if( ddrval != DD_OK )
|
|
{
|
|
Msg("Cant attach clipper to front buffer");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* init the color key
|
|
*/
|
|
ddpf.dwSize = sizeof(ddpf);
|
|
IDirectDrawSurface_GetPixelFormat(lpFrontBuffer, &ddpf);
|
|
|
|
/*
|
|
* we use white as the color key, if we are in a 8bpp mode, we know
|
|
* what white is (because we use a 332 palette) if we are not in a
|
|
* a 8bpp mode we dont know what white is and we need to figure it
|
|
* out from the device (remember 16bpp comes in two common flavors
|
|
* 555 and 565). if we wanted to any random color as the color key
|
|
* we would call DDColorMatch (see below) to convert a RGB into a
|
|
* physical color.
|
|
*/
|
|
if (ddpf.dwRGBBitCount == 8)
|
|
dwColorKey = 0xff;
|
|
else
|
|
dwColorKey = ddpf.dwRBitMask | ddpf.dwGBitMask | ddpf.dwBBitMask;
|
|
|
|
Msg("dwColorKey = 0x%08lX", dwColorKey);
|
|
|
|
if( bTransDest )
|
|
{
|
|
DDCOLORKEY ddck;
|
|
ddck.dwColorSpaceLowValue = dwColorKey;
|
|
ddck.dwColorSpaceHighValue = dwColorKey;
|
|
IDirectDrawSurface_SetColorKey( lpBackBuffer, DDCKEY_DESTBLT, &ddck);
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* DDCreateFlippingSurface */
|
|
|
|
/*
|
|
* DDCreateSurface
|
|
*/
|
|
LPDIRECTDRAWSURFACE DDCreateSurface(
|
|
DWORD width,
|
|
DWORD height,
|
|
BOOL sysmem,
|
|
BOOL trans )
|
|
{
|
|
DDSURFACEDESC ddsd;
|
|
HRESULT ddrval;
|
|
DDCOLORKEY ddck;
|
|
LPDIRECTDRAWSURFACE psurf;
|
|
|
|
|
|
/*
|
|
* fill in surface desc
|
|
*/
|
|
memset( &ddsd, 0, sizeof( ddsd ) );
|
|
ddsd.dwSize = sizeof( ddsd );
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
|
|
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
if( sysmem || bUseSysMem )
|
|
{
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
}
|
|
|
|
ddsd.dwHeight = height;
|
|
ddsd.dwWidth = width;
|
|
|
|
ddrval = IDirectDraw_CreateSurface( lpDD, &ddsd, &psurf, NULL );
|
|
|
|
/*
|
|
* set the color key for this bitmap
|
|
*/
|
|
if( ddrval == DD_OK )
|
|
{
|
|
if( trans && !bTransDest )
|
|
{
|
|
ddck.dwColorSpaceLowValue = dwColorKey;
|
|
ddck.dwColorSpaceHighValue = dwColorKey;
|
|
IDirectDrawSurface_SetColorKey( psurf, DDCKEY_SRCBLT, &ddck);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Msg( "CreateSurface FAILED, rc = %ld", (DWORD) LOWORD( ddrval ) );
|
|
psurf = NULL;
|
|
}
|
|
|
|
return psurf;
|
|
|
|
} /* DDCreateSurface */
|
|
|
|
DWORD DDColorMatch(IDirectDrawSurface *pdds, COLORREF rgb)
|
|
{
|
|
COLORREF rgbT;
|
|
HDC hdc;
|
|
DWORD dw = CLR_INVALID;
|
|
DDSURFACEDESC ddsd;
|
|
HRESULT hres;
|
|
|
|
if (IDirectDrawSurface_GetDC(pdds, &hdc) == DD_OK)
|
|
{
|
|
rgbT = GetPixel(hdc, 0, 0);
|
|
SetPixel(hdc, 0, 0, rgb);
|
|
IDirectDrawSurface_ReleaseDC(pdds, hdc);
|
|
}
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
hres = IDirectDrawSurface_Lock(
|
|
pdds, NULL, &ddsd, DDLOCK_WAIT, NULL);
|
|
|
|
if (hres == DD_OK)
|
|
{
|
|
dw = *(DWORD *)ddsd.lpSurface;
|
|
if(ddsd.ddpfPixelFormat.dwRGBBitCount != 32)
|
|
dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount)-1;
|
|
IDirectDrawSurface_Unlock(pdds, NULL);
|
|
}
|
|
else
|
|
{
|
|
IDirectDrawSurface_GetSurfaceDesc(pdds,&ddsd);
|
|
if(ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
|
|
Msg("Failed to lock Primary Surface!");
|
|
else
|
|
Msg("Failed to lock NON-PRIMARY Surface!");
|
|
}
|
|
|
|
if (IDirectDrawSurface_GetDC(pdds, &hdc) == DD_OK)
|
|
{
|
|
SetPixel(hdc, 0, 0, rgbT);
|
|
IDirectDrawSurface_ReleaseDC(pdds, hdc);
|
|
}
|
|
|
|
return dw;
|
|
}
|
|
|
|
/*
|
|
* ReadPalFile
|
|
*
|
|
* Create a DirectDrawPalette from a palette file
|
|
*
|
|
* if the palette files cant be found, make a default 332 palette
|
|
*/
|
|
LPDIRECTDRAWPALETTE ReadPalFile( char *fname )
|
|
{
|
|
int i;
|
|
int fh;
|
|
HRESULT ddrval;
|
|
IDirectDrawPalette *ppal;
|
|
|
|
struct {
|
|
DWORD dwRiff;
|
|
DWORD dwFileSize;
|
|
DWORD dwPal;
|
|
DWORD dwData;
|
|
DWORD dwDataSize;
|
|
WORD palVersion;
|
|
WORD palNumEntries;
|
|
PALETTEENTRY ape[256];
|
|
} pal;
|
|
|
|
pal.dwRiff = 0;
|
|
|
|
if (fname)
|
|
{
|
|
fh = _lopen( fname, OF_READ);
|
|
|
|
if (fh != -1)
|
|
{
|
|
_lread(fh, &pal, sizeof(pal));
|
|
_lclose(fh);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* if the file is not a palette file, or does not exist
|
|
* default to a 332 palette
|
|
*/
|
|
if (pal.dwRiff != 0x46464952 || // 'RIFF'
|
|
pal.dwPal != 0x204C4150 || // 'PAL '
|
|
pal.dwData != 0x61746164 || // 'data'
|
|
pal.palVersion != 0x0300 ||
|
|
pal.palNumEntries > 256 ||
|
|
pal.palNumEntries < 1)
|
|
{
|
|
Msg("Can't open palette file, using default 332.");
|
|
|
|
for( i=0; i<256; i++ )
|
|
{
|
|
pal.ape[i].peRed = (BYTE)(((i >> 5) & 0x07) * 255 / 7);
|
|
pal.ape[i].peGreen = (BYTE)(((i >> 2) & 0x07) * 255 / 7);
|
|
pal.ape[i].peBlue = (BYTE)(((i >> 0) & 0x03) * 255 / 3);
|
|
pal.ape[i].peFlags = (BYTE)0;
|
|
}
|
|
}
|
|
|
|
ddrval = IDirectDraw_CreatePalette(
|
|
lpDD,
|
|
DDPCAPS_8BIT,
|
|
pal.ape,
|
|
&ppal,
|
|
NULL );
|
|
return ppal;
|
|
|
|
} /* ReadPalFile */
|
|
|
|
|
|
/*
|
|
* Splash
|
|
*
|
|
* Draw a splash screen during startup
|
|
* NOTE the screen has been cleared in DDCreateFlippingSurface
|
|
*/
|
|
void Splash( void )
|
|
{
|
|
HDC hdc;
|
|
HRESULT err;
|
|
|
|
DDClear();
|
|
|
|
if ((err = IDirectDrawSurface_GetDC(lpFrontBuffer, &hdc)) == DD_OK)
|
|
{
|
|
char *szMsg = "FoxBear is loading.......please wait.";
|
|
SetTextColor(hdc, RGB(255,255,255));
|
|
SetBkMode(hdc, TRANSPARENT);
|
|
TextOut(hdc, rcWindow.left, rcWindow.top, szMsg, lstrlen(szMsg));
|
|
IDirectDrawSurface_ReleaseDC(lpFrontBuffer, hdc);
|
|
}
|
|
else
|
|
{
|
|
Msg("GetDC failed! 0x%x",err);
|
|
}
|
|
|
|
} /* Splash */
|
|
|
|
/*
|
|
* MEMORY ALLOCATION ROUTINES...
|
|
*/
|
|
|
|
/*
|
|
* MemAlloc
|
|
*/
|
|
LPVOID MemAlloc( UINT size )
|
|
{
|
|
LPVOID ptr;
|
|
|
|
ptr = LocalAlloc( LPTR, size );
|
|
return ptr;
|
|
|
|
} /* MemAlloc */
|
|
|
|
/*
|
|
* CMemAlloc
|
|
*/
|
|
LPVOID CMemAlloc( UINT cnt, UINT isize )
|
|
{
|
|
DWORD size;
|
|
LPVOID ptr;
|
|
|
|
size = cnt * isize;
|
|
ptr = LocalAlloc( LPTR, size );
|
|
return ptr;
|
|
|
|
} /* CMemAlloc */
|
|
|
|
/*
|
|
* MemFree
|
|
*/
|
|
void MemFree( LPVOID ptr )
|
|
{
|
|
if( ptr != NULL )
|
|
{
|
|
LocalFree( ptr );
|
|
}
|
|
|
|
} /* MemFree */
|
|
|
|
HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context)
|
|
{
|
|
Msg("Mode: %dx%dx%d", pddsd->dwWidth, pddsd->dwHeight,pddsd->ddpfPixelFormat.dwRGBBitCount);
|
|
if(
|
|
(ModeList[NumModes-1].w == (int)pddsd->dwWidth)&&
|
|
(ModeList[NumModes-1].h == (int)pddsd->dwHeight)&&
|
|
(ModeList[NumModes-1].bpp == (int)pddsd->ddpfPixelFormat.dwRGBBitCount)
|
|
)
|
|
return DDENUMRET_OK;
|
|
ModeList[NumModes].w = pddsd->dwWidth;
|
|
ModeList[NumModes].h = pddsd->dwHeight;
|
|
ModeList[NumModes].bpp = pddsd->ddpfPixelFormat.dwRGBBitCount;
|
|
NumModes++;
|
|
|
|
return DDENUMRET_OK;
|
|
}
|