DDRAW.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"

typedef struct {
GUID *guid;
GUID DriverGUID;
CHAR DriverDesc[128];
CHAR DriverName[128];
} Devices;

Devices aDDDevs[15];
int MaxDevIndex = 0;
int DevIndex = 0;

BOOL bUseEmulation;
BOOL bUseSysMem;
int nBufferCount;
int CmdLineBufferCount;
BOOLbTransDest;
BOOL bColorFill;

HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context);

HRESULT CALLBACK DDEnumCallback(GUID * lpGUID, LPSTR DRiverDesc, LPSTR DriverName, LPVOID lpContext);

/*
* DDInit
*/
BOOL DDInit( void )
{
DirectDrawEnumerate(&DDEnumCallback,NULL);
DDEnumCallback((GUID *)DDCREATE_EMULATIONONLY, "Hardware Emulation Layer", "", NULL);
return TRUE;
}
/*
* DDEnable
*/
BOOL DDEnable( void )
{
LPDIRECTDRAWlpdd;
LPDIRECTDRAW2 lpdd2;
DDCAPS ddcaps;
HRESULTddrval;
BOOLuse_dest;
OSVERSIONINFO osv;

osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
//
//What are we running on ?
//
GetVersionEx(&osv);


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) || (lpDD2 == NULL))
{
if( bUseEmulation)
DevIndex = MaxDevIndex-1;
ddrval = DirectDrawCreate(aDDDevs[DevIndex].guid,&lpdd,NULL);
if(ddrval == DD_OK)
{
ddrval = IDirectDraw_QueryInterface(lpdd, &IID_IDirectDraw2, &lpdd2);
}
}
else
{
lpdd = lpDD;
lpdd2 = lpDD2;
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 );

ddrval = IDirectDraw_EnumDisplayModes(lpdd, DDEDM_STANDARDVGAMODES, NULL, 0, EnumDisplayModesCallback);
if(ddrval != DD_OK)
{
ddrval = 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);
if((GameMode.cx == 320) && (GameMode.cy == 200) && (GameBPP == 8))
{
ddrval = IDirectDraw2_SetDisplayMode(lpdd2, GameMode.cx, GameMode.cy, GameBPP,0,DDSDM_STANDARDVGAMODE);
} else {
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;
lpDD2 = lpdd2;
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 );
IDirectDraw_Release( lpDD2 );
lpDD = NULL;
}
}

return TRUE;
}

/*
* DDClear
*
* clear the front buffer and all backbuffers.
*/
BOOL DDClear( void )
{
DDBLTFX ddbltfx;
inti;
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;
DDSURFACEDESCddsd;
HRESULTddrval;
DDSCAPSddscaps;
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 )
{
DDCOLORKEYddck;
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 )
{
DDSURFACEDESCddsd;
HRESULTddrval;
DDCOLORKEYddck;
LPDIRECTDRAWSURFACEpsurf;


/*
* 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;
intfh;
HRESULTddrval;
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 = 0;

DDClear();

// if ((err = IDirectDrawSurface_GetDC(lpFrontBuffer, &hdc)) == DD_OK)
if ((hdc = GetDC(hWndMain)) )
{
char ach[256];
int len;

len = wsprintf(ach,
"FoxBear is loading...... Device:%s %s",
aDDDevs[DevIndex].DriverDesc, aDDDevs[DevIndex].DriverName);

SetTextColor(hdc, RGB(255,255,255));
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, rcWindow.left, rcWindow.top, ach, len);

//IDirectDrawSurface_ReleaseDC(lpFrontBuffer, hdc);
ReleaseDC(hWndMain,hdc);
}
else
{
Msg("GetDC failed! 0x%x",err);
}

} /* Splash */

/*
* MEMORY ALLOCATION ROUTINES...
*/

/*
* MemAlloc
*/
LPVOID MemAlloc( UINT size )
{
LPVOIDptr;

ptr = LocalAlloc( LPTR, size );
return ptr;

} /* MemAlloc */

/*
* CMemAlloc
*/
LPVOID CMemAlloc( UINT cnt, UINT isize )
{
DWORDsize;
LPVOIDptr;

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)
{
int ChkMode;

Msg("Mode: %dx%dx%d", pddsd->dwWidth, pddsd->dwHeight,pddsd->ddpfPixelFormat.dwRGBBitCount);

for(ChkMode = 0;ChkMode < NumModes;ChkMode++)
{
if(
(ModeList[ChkMode].w == (int)pddsd->dwWidth)&&
(ModeList[ChkMode].h == (int)pddsd->dwHeight)&&
(ModeList[ChkMode].bpp == (int)pddsd->ddpfPixelFormat.dwRGBBitCount)&&
(ModeList[ChkMode].dwFlags == (int)pddsd->ddsCaps.dwCaps)
)
return DDENUMRET_OK;
}

ModeList[NumModes].w = pddsd->dwWidth;
ModeList[NumModes].h = pddsd->dwHeight;
ModeList[NumModes].bpp = pddsd->ddpfPixelFormat.dwRGBBitCount;
ModeList[NumModes].dwFlags = pddsd->ddsCaps.dwCaps;

NumModes++;

return DDENUMRET_OK;
}

HRESULT CALLBACK DDEnumCallback(GUID * lpGUID, LPSTR DriverDesc, LPSTR DriverName, LPVOID lpContext)
{
if(MaxDevIndex >= sizeof(aDDDevs)/sizeof(aDDDevs[0]))
return E_FAIL;

Msg("Device: %s (%s)", DriverDesc, DriverName);

if(lpGUID == NULL || lpGUID == (GUID*)DDCREATE_EMULATIONONLY)
{
aDDDevs[MaxDevIndex].guid = lpGUID;
}
else
{
aDDDevs[MaxDevIndex].DriverGUID = *lpGUID;
aDDDevs[MaxDevIndex].guid = &aDDDevs[MaxDevIndex].DriverGUID;
}

lstrcpyn(aDDDevs[MaxDevIndex].DriverDesc, DriverDesc, 128);
lstrcpyn(aDDDevs[MaxDevIndex].DriverName, DriverName, 128);

MaxDevIndex++;
return DDENUMRET_OK;
}