Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
489 lines
16 KiB
C++
489 lines
16 KiB
C++
// EnumD3D.cpp: implementation of the CEnumD3D class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "EnumD3D.h"
|
|
#include <dsound.h>
|
|
#include "GMMemory.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
D3DAdapterInfo CEnumD3D::m_Adapters[10];
|
|
DWORD CEnumD3D::m_dwNumAdapters;
|
|
DWORD CEnumD3D::m_dwAdapter;
|
|
BOOL CEnumD3D::m_bWindowed;
|
|
LPDIRECT3D8 CEnumD3D::m_pD3D;
|
|
BOOL CEnumD3D::m_bUseDepthBuffer;
|
|
long CEnumD3D::m_dwMinDepthBits;
|
|
long CEnumD3D::m_dwMinStencilBits;
|
|
|
|
long CEnumD3D::m_nAdapter;
|
|
long CEnumD3D::m_nDevice;
|
|
long CEnumD3D::m_nMode;
|
|
|
|
TCHAR CEnumD3D::m_strSoundCard[64];
|
|
TCHAR CEnumD3D::m_strSoundCardDrv[64];
|
|
|
|
|
|
int SortModesCallback( const VOID* arg1, const VOID* arg2 )
|
|
{
|
|
D3DDISPLAYMODE* p1 = (D3DDISPLAYMODE*)arg1;
|
|
D3DDISPLAYMODE* p2 = (D3DDISPLAYMODE*)arg2;
|
|
|
|
if( p1->Format > p2->Format ) return -1;
|
|
if( p1->Format < p2->Format ) return +1;
|
|
if( p1->Width < p2->Width ) return -1;
|
|
if( p1->Width > p2->Width ) return +1;
|
|
if( p1->Height < p2->Height ) return -1;
|
|
if( p1->Height > p2->Height ) return +1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID EnumSound();
|
|
BOOL CALLBACK
|
|
DSoundEnumProc(LPGUID lpGUID,
|
|
LPCTSTR lpszDesc,
|
|
LPCTSTR lpszDrvName,
|
|
LPVOID lpContext );
|
|
|
|
CEnumD3D::CEnumD3D()
|
|
{
|
|
m_bUseDepthBuffer=true;
|
|
m_nAdapter=m_nDevice=m_nMode=0;
|
|
}
|
|
|
|
CEnumD3D::~CEnumD3D()
|
|
{
|
|
|
|
}
|
|
|
|
HRESULT CEnumD3D::Enum()
|
|
{
|
|
m_pD3D=Direct3DCreate8(D3D_SDK_VERSION);
|
|
const DWORD dwNumDeviceTypes = 2;
|
|
const TCHAR* strDeviceDescs[] = { "HAL", "REF" };
|
|
const D3DDEVTYPE DeviceTypes[] = { D3DDEVTYPE_HAL, D3DDEVTYPE_REF };
|
|
|
|
BOOL bHALExists = FALSE;
|
|
BOOL bHALIsWindowedCompatible = FALSE;
|
|
BOOL bHALIsDesktopCompatible = FALSE;
|
|
BOOL bHALIsSampleCompatible = FALSE;
|
|
|
|
// Loop through all the adapters on the system (usually, there's just one
|
|
// unless more than one graphics card is present).
|
|
m_dwNumAdapters=0;
|
|
for( UINT iAdapter = 0; iAdapter < m_pD3D->GetAdapterCount(); iAdapter++ )
|
|
{
|
|
// Fill in adapter info
|
|
D3DAdapterInfo* pAdapter = &m_Adapters[m_dwNumAdapters];
|
|
m_pD3D->GetAdapterIdentifier( iAdapter, 0, &pAdapter->d3dAdapterIdentifier );
|
|
m_pD3D->GetAdapterDisplayMode( iAdapter, &pAdapter->d3ddmDesktop );
|
|
pAdapter->dwNumDevices = 0;
|
|
pAdapter->dwCurrentDevice = 0;
|
|
|
|
// Enumerate all display modes on this adapter
|
|
CD3DDISPLAYMODE modes[100];
|
|
D3DFORMAT formats[20];
|
|
DWORD dwNumFormats = 0;
|
|
DWORD dwNumModes = 0;
|
|
DWORD dwNumAdapterModes = m_pD3D->GetAdapterModeCount( iAdapter );
|
|
|
|
// Add the adapter's current desktop format to the list of formats
|
|
formats[dwNumFormats++] = pAdapter->d3ddmDesktop.Format;
|
|
|
|
DWORD dwRefreshCount = 0;
|
|
ZeroMemory(&modes[0].RefreshRate, sizeof(modes[0].RefreshRate));
|
|
for( UINT iMode = 0; iMode < dwNumAdapterModes; iMode++ )
|
|
{
|
|
// Get the display mode attributes
|
|
D3DDISPLAYMODE DisplayMode;
|
|
m_pD3D->EnumAdapterModes( iAdapter, iMode, &DisplayMode );
|
|
|
|
// Filter out low-resolution modes
|
|
if( DisplayMode.Width < 640 || DisplayMode.Height < 400 )
|
|
continue;
|
|
|
|
// Check if the mode already exists (to filter out refresh rates)
|
|
DWORD m=0L;
|
|
for( ; m<dwNumModes; m++ )
|
|
{
|
|
if( ( modes[m].Width == DisplayMode.Width ) &&
|
|
( modes[m].Height == DisplayMode.Height ) &&
|
|
( modes[m].Format == DisplayMode.Format ) )
|
|
break;
|
|
}
|
|
|
|
// If we found a new mode, add it to the list of modes
|
|
if( m == dwNumModes )
|
|
{
|
|
dwRefreshCount = 0;
|
|
ZeroMemory(&modes[dwNumModes].RefreshRate, sizeof(modes[dwNumModes].RefreshRate));
|
|
modes[dwNumModes].RefreshRate[dwRefreshCount++] = DisplayMode.RefreshRate;
|
|
modes[dwNumModes].Width = DisplayMode.Width;
|
|
modes[dwNumModes].Height = DisplayMode.Height;
|
|
modes[dwNumModes].Format = DisplayMode.Format;
|
|
dwNumModes++;
|
|
|
|
// Check if the mode's format already exists
|
|
DWORD f=0;
|
|
for( ; f<dwNumFormats; f++ )
|
|
{
|
|
if( DisplayMode.Format == formats[f] )
|
|
break;
|
|
}
|
|
|
|
// If the format is new, add it to the list
|
|
if( f== dwNumFormats )
|
|
formats[dwNumFormats++] = DisplayMode.Format;
|
|
} else
|
|
{
|
|
modes[m].RefreshRate[dwRefreshCount++] = DisplayMode.RefreshRate;
|
|
}
|
|
}
|
|
|
|
// Sort the list of display modes (by format, then width, then height)
|
|
// qsort( modes, dwNumModes, sizeof(CD3DDISPLAYMODE), SortModesCallback );
|
|
|
|
// Add devices to adapter
|
|
for( UINT iDevice = 0; iDevice < dwNumDeviceTypes; iDevice++ )
|
|
{
|
|
// Fill in device info
|
|
D3DDeviceInfo* pDevice;
|
|
pDevice = &pAdapter->devices[pAdapter->dwNumDevices];
|
|
pDevice->DeviceType = DeviceTypes[iDevice];
|
|
m_pD3D->GetDeviceCaps( iAdapter, DeviceTypes[iDevice], &pDevice->d3dCaps );
|
|
pDevice->strDesc = strDeviceDescs[iDevice];
|
|
pDevice->dwNumModes = 0;
|
|
pDevice->dwCurrentMode = 0;
|
|
pDevice->bCanDoWindowed = FALSE;
|
|
pDevice->bWindowed = FALSE;
|
|
pDevice->MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
|
|
// Examine each format supported by the adapter to see if it will
|
|
// work with this device and meets the needs of the application.
|
|
BOOL bFormatConfirmed[20];
|
|
DWORD dwBehavior[20];
|
|
D3DFORMAT fmtDepthStencil[20];
|
|
|
|
for( DWORD f=0; f<dwNumFormats; f++ )
|
|
{
|
|
bFormatConfirmed[f] = FALSE;
|
|
fmtDepthStencil[f] = D3DFMT_UNKNOWN;
|
|
|
|
// Skip formats that cannot be used as render targets on this device
|
|
if( FAILED( m_pD3D->CheckDeviceType( iAdapter, pDevice->DeviceType,
|
|
formats[f], formats[f], FALSE ) ) )
|
|
continue;
|
|
|
|
if( pDevice->DeviceType == D3DDEVTYPE_HAL )
|
|
{
|
|
// This system has a HAL device
|
|
bHALExists = TRUE;
|
|
|
|
if( pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED )
|
|
{
|
|
// HAL can run in a window for some mode
|
|
bHALIsWindowedCompatible = TRUE;
|
|
|
|
if( f == 0 )
|
|
{
|
|
// HAL can run in a window for the current desktop mode
|
|
bHALIsDesktopCompatible = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Confirm the device/format for HW vertex processing
|
|
if( pDevice->d3dCaps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT )
|
|
{
|
|
if( pDevice->d3dCaps.DevCaps&D3DDEVCAPS_PUREDEVICE )
|
|
{
|
|
/*
|
|
dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING |
|
|
D3DCREATE_PUREDEVICE;
|
|
*/
|
|
dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
|
|
|
if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f],
|
|
formats[f] ) ) )
|
|
bFormatConfirmed[f] = FALSE;
|
|
}
|
|
|
|
if ( FALSE == bFormatConfirmed[f] )
|
|
{
|
|
dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
|
|
|
if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f],
|
|
formats[f] ) ) )
|
|
bFormatConfirmed[f] = TRUE;
|
|
}
|
|
|
|
if ( FALSE == bFormatConfirmed[f] )
|
|
{
|
|
dwBehavior[f] = D3DCREATE_MIXED_VERTEXPROCESSING;
|
|
|
|
if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f],
|
|
formats[f] ) ) )
|
|
bFormatConfirmed[f] = TRUE;
|
|
}
|
|
}
|
|
|
|
// Confirm the device/format for SW vertex processing
|
|
if( FALSE == bFormatConfirmed[f] )
|
|
{
|
|
dwBehavior[f] = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
|
|
if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f],
|
|
formats[f] ) ) )
|
|
bFormatConfirmed[f] = TRUE;
|
|
}
|
|
|
|
// Find a suitable depth/stencil buffer format for this device/format
|
|
if( bFormatConfirmed[f])
|
|
{
|
|
if( !FindDepthStencilFormat( iAdapter, pDevice->DeviceType,
|
|
formats[f], &fmtDepthStencil[f] ) )
|
|
{
|
|
bFormatConfirmed[f] = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add all enumerated display modes with confirmed formats to the
|
|
// device's list of valid modes
|
|
DWORD m=0L;
|
|
for( ; m<dwNumModes; m++ )
|
|
{
|
|
for( DWORD f=0; f<dwNumFormats; f++ )
|
|
{
|
|
if( modes[m].Format == formats[f] )
|
|
{
|
|
if( bFormatConfirmed[f] == TRUE )
|
|
{
|
|
// Add this mode to the device's list of valid modes
|
|
pDevice->modes[pDevice->dwNumModes].Width = modes[m].Width;
|
|
pDevice->modes[pDevice->dwNumModes].Height = modes[m].Height;
|
|
pDevice->modes[pDevice->dwNumModes].Format = modes[m].Format;
|
|
pDevice->modes[pDevice->dwNumModes].dwBehavior = dwBehavior[f];
|
|
pDevice->modes[pDevice->dwNumModes].DepthStencilFormat = fmtDepthStencil[f];
|
|
|
|
for( DWORD r = 0; r < 50; ++r )
|
|
{
|
|
pDevice->modes[pDevice->dwNumModes].dwRefresh[r] = modes[m].RefreshRate[r];
|
|
}
|
|
|
|
pDevice->dwNumModes++;
|
|
|
|
if( pDevice->DeviceType == D3DDEVTYPE_HAL )
|
|
bHALIsSampleCompatible = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Select any 640x480 mode for default (but prefer a 16-bit mode)
|
|
for( m=0; m<pDevice->dwNumModes; m++ )
|
|
{
|
|
if( pDevice->modes[m].Width==640 && pDevice->modes[m].Height==480 )
|
|
{
|
|
pDevice->dwCurrentMode = m;
|
|
if( pDevice->modes[m].Format == D3DFMT_R5G6B5 ||
|
|
pDevice->modes[m].Format == D3DFMT_X1R5G5B5 ||
|
|
pDevice->modes[m].Format == D3DFMT_A1R5G5B5 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check if the device is compatible with the desktop display mode
|
|
// (which was added initially as formats[0])
|
|
if( bFormatConfirmed[0] && (pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) )
|
|
{
|
|
pDevice->bCanDoWindowed = TRUE;
|
|
pDevice->bWindowed = TRUE;
|
|
}
|
|
|
|
// If valid modes were found, keep this device
|
|
if( pDevice->dwNumModes > 0 )
|
|
pAdapter->dwNumDevices++;
|
|
}
|
|
|
|
// If valid devices were found, keep this adapter
|
|
if( pAdapter->dwNumDevices > 0 )
|
|
m_dwNumAdapters++;
|
|
}
|
|
|
|
// Return an error if no compatible devices were found
|
|
if( 0L == m_dwNumAdapters )
|
|
return S_OK;
|
|
|
|
// Pick a default device that can render into a window
|
|
// (This code assumes that the HAL device comes before the REF
|
|
// device in the device array).
|
|
m_pD3D->Release();
|
|
EnumSound();
|
|
|
|
for( DWORD a=0; a<m_dwNumAdapters; a++ )
|
|
{
|
|
for( DWORD d=0; d < m_Adapters[a].dwNumDevices; d++ )
|
|
{
|
|
if( m_Adapters[a].devices[d].bWindowed )
|
|
{
|
|
m_Adapters[a].dwCurrentDevice = d;
|
|
m_dwAdapter = a;
|
|
m_bWindowed = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL CEnumD3D::FindDepthStencilFormat(UINT iAdapter, D3DDEVTYPE DeviceType, D3DFORMAT TargetFormat, D3DFORMAT *pDepthStencilFormat)
|
|
{
|
|
if( m_dwMinDepthBits <= 16 && m_dwMinStencilBits == 0 )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType,
|
|
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType,
|
|
TargetFormat, TargetFormat, D3DFMT_D16 ) ) )
|
|
{
|
|
*pDepthStencilFormat = D3DFMT_D16;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( m_dwMinDepthBits <= 15 && m_dwMinStencilBits <= 1 )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType,
|
|
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D15S1 ) ) )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType,
|
|
TargetFormat, TargetFormat, D3DFMT_D15S1 ) ) )
|
|
{
|
|
*pDepthStencilFormat = D3DFMT_D15S1;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits == 0 )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType,
|
|
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType,
|
|
TargetFormat, TargetFormat, D3DFMT_D24X8 ) ) )
|
|
{
|
|
*pDepthStencilFormat = D3DFMT_D24X8;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits <= 8 )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType,
|
|
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType,
|
|
TargetFormat, TargetFormat, D3DFMT_D24S8 ) ) )
|
|
{
|
|
*pDepthStencilFormat = D3DFMT_D24S8;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( m_dwMinDepthBits <= 24 && m_dwMinStencilBits <= 4 )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType,
|
|
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X4S4 ) ) )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType,
|
|
TargetFormat, TargetFormat, D3DFMT_D24X4S4 ) ) )
|
|
{
|
|
*pDepthStencilFormat = D3DFMT_D24X4S4;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( m_dwMinDepthBits <= 32 && m_dwMinStencilBits == 0 )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType,
|
|
TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32 ) ) )
|
|
{
|
|
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType,
|
|
TargetFormat, TargetFormat, D3DFMT_D32 ) ) )
|
|
{
|
|
*pDepthStencilFormat = D3DFMT_D32;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT CEnumD3D::ConfirmDevice(D3DCAPS8 *, DWORD, D3DFORMAT)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
VOID EnumSound()
|
|
{
|
|
|
|
LPDIRECTSOUND8 pDS;
|
|
if( FAILED(DirectSoundCreate8(NULL, &pDS, NULL)) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (FAILED(DirectSoundEnumerate((LPDSENUMCALLBACK)DSoundEnumProc,
|
|
NULL)))
|
|
{
|
|
if( pDS )
|
|
{
|
|
pDS->Release();
|
|
pDS = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
if( pDS )
|
|
{
|
|
pDS->Release();
|
|
pDS = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
BOOL CALLBACK DSoundEnumProc(LPGUID lpGUID,
|
|
LPCTSTR lpszDesc,
|
|
LPCTSTR lpszDrvName,
|
|
LPVOID lpContext )
|
|
{
|
|
HWND hCombo = (HWND)lpContext;
|
|
LPGUID lpTemp = NULL;
|
|
|
|
|
|
if (lpGUID != NULL) // NULL only for "Primary Sound Driver".
|
|
{
|
|
strcpy( CEnumD3D::m_strSoundCard, lpszDesc );
|
|
strcpy( CEnumD3D::m_strSoundCardDrv, lpszDrvName );
|
|
}
|
|
|
|
|
|
return(TRUE);
|
|
} |