Skip to content

Commit

Permalink
Add cache for Cap9
Browse files Browse the repository at this point in the history
Allows EnumDevices() to work even when ddrawParent has been released
  • Loading branch information
elishacloud committed Mar 2, 2024
1 parent 207ec5d commit 61404cc
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 87 deletions.
2 changes: 1 addition & 1 deletion Dllmain/BuildNo.rc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
#define BUILD_NUMBER 6948
#define BUILD_NUMBER 6949
188 changes: 104 additions & 84 deletions ddraw/IDirect3DX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,35 @@ HRESULT m_IDirect3DX::EnumDevices(LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback
}
}

void m_IDirect3DX::GetCap9Cache()
{
// Check for device
if (ddrawParent)
{
// Get d3d9Object
IDirect3D9* d3d9Object = ddrawParent->GetDirect3D9Object();
if (d3d9Object)
{
UINT AdapterCount = d3d9Object->GetAdapterCount();
if (AdapterCount)
{
Cap9Cache.clear();

// Loop through all adapters
for (UINT i = 0; i < AdapterCount; i++)
{
// Get Device Caps
DUALCAP9 DCaps9;
if (SUCCEEDED(d3d9Object->GetDeviceCaps(i, D3DDEVTYPE_REF, &DCaps9.REF)) && SUCCEEDED(d3d9Object->GetDeviceCaps(i, D3DDEVTYPE_HAL, &DCaps9.HAL)))
{
Cap9Cache.push_back(DCaps9);
}
}
}
}
}
}

HRESULT m_IDirect3DX::EnumDevices7(LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallback7, LPVOID lpUserArg, DWORD DirectXVersion)
{
Logging::LogDebug() << __FUNCTION__ << " (" << this << ")";
Expand All @@ -225,111 +254,99 @@ HRESULT m_IDirect3DX::EnumDevices7(LPD3DENUMDEVICESCALLBACK7 lpEnumDevicesCallba
return DDERR_INVALIDPARAMS;
}

// Check for device
if (!ddrawParent)
// Conversion callback
LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback = (LPD3DENUMDEVICESCALLBACK)lpEnumDevicesCallback7;

// Update Cap9 cache
GetCap9Cache();

// Check cache
if (Cap9Cache.empty())
{
LOG_LIMIT(100, __FUNCTION__ << " Error: no ddraw parent!");
LOG_LIMIT(100, __FUNCTION__ << " Error: could not get Cap9 cache!");
return DDERR_INVALIDOBJECT;
}

// Get d3d9Object
IDirect3D9 *d3d9Object = ddrawParent->GetDirect3D9Object();
UINT AdapterCount = d3d9Object->GetAdapterCount();

// Conversion callback
LPD3DENUMDEVICESCALLBACK lpEnumDevicesCallback = (LPD3DENUMDEVICESCALLBACK)lpEnumDevicesCallback7;

// Loop through all adapters
for (UINT i = 0; i < AdapterCount; i++)
for (auto& entry : Cap9Cache)
{
for (D3DDEVTYPE Type : {D3DDEVTYPE_REF, D3DDEVTYPE_HAL, (D3DDEVTYPE)(D3DDEVTYPE_HAL + 0x10)})
for (int x = 0; x < 3; x++)
{
// Get Device Caps
D3DCAPS9 Caps9;
HRESULT hr = d3d9Object->GetDeviceCaps(i, (D3DDEVTYPE)((DWORD)Type & ~0x10), &Caps9);
D3DCAPS9 Caps9 = (x == 0) ? entry.REF : entry.HAL;
D3DDEVTYPE Type = (x == 0) ? D3DDEVTYPE_REF : (x == 1) ? D3DDEVTYPE_HAL : (D3DDEVTYPE)(D3DDEVTYPE_HAL + 0x10);

if (SUCCEEDED(hr))
// Convert device desc
D3DDEVICEDESC7 DeviceDesc7;
Caps9.DeviceType = Type;
ConvertDeviceDesc(DeviceDesc7, Caps9);

GUID deviceGUID = DeviceDesc7.deviceGUID;
char lpName[MAX_PATH] = {}, lpDescription[MAX_PATH] = {};

// For conversion
D3DDEVICEDESC D3DDRVDevDesc = {}, D3DSWDevDesc = {};
DWORD DevSize = (DirectXVersion == 1) ? D3DDEVICEDESC1_SIZE :
(DirectXVersion == 2) ? D3DDEVICEDESC5_SIZE :
(DirectXVersion == 3) ? D3DDEVICEDESC6_SIZE : sizeof(D3DDEVICEDESC);
D3DDRVDevDesc.dwSize = DevSize;
D3DSWDevDesc.dwSize = DevSize;

switch ((DWORD)Type)
{
// Convert device desc
D3DDEVICEDESC7 DeviceDesc7;
Caps9.DeviceType = Type;
ConvertDeviceDesc(DeviceDesc7, Caps9);

GUID deviceGUID = DeviceDesc7.deviceGUID;
char lpName[MAX_PATH] = {}, lpDescription[MAX_PATH] = {};

// For conversion
D3DDEVICEDESC D3DDRVDevDesc = {}, D3DSWDevDesc = {};
DWORD DevSize = (DirectXVersion == 1) ? D3DDEVICEDESC1_SIZE :
(DirectXVersion == 2) ? D3DDEVICEDESC5_SIZE :
(DirectXVersion == 3) ? D3DDEVICEDESC6_SIZE : sizeof(D3DDEVICEDESC);
D3DDRVDevDesc.dwSize = DevSize;
D3DSWDevDesc.dwSize = DevSize;

switch ((DWORD)Type)
case D3DDEVTYPE_REF:
strcpy_s(lpName, "RGB Emulation");
strcpy_s(lpDescription, "Microsoft Direct3D RGB Software Emulation");
if (DirectXVersion < 7)
{
case D3DDEVTYPE_REF:
strcpy_s(lpName, "RGB Emulation");
strcpy_s(lpDescription, "Microsoft Direct3D RGB Software Emulation");
if (DirectXVersion < 7)
{
// Get D3DSWDevDesc data (D3DDEVTYPE_REF)
ConvertDeviceDesc(D3DSWDevDesc, DeviceDesc7);

// Get D3DDRVDevDesc data (D3DDEVTYPE_HAL)
if (SUCCEEDED(d3d9Object->GetDeviceCaps(i, D3DDEVTYPE_HAL, &Caps9)))
{
Caps9.DeviceType = D3DDEVTYPE_HAL;
ConvertDeviceDesc(DeviceDesc7, Caps9);
ConvertDeviceDesc(D3DDRVDevDesc, DeviceDesc7);

if (lpEnumDevicesCallback(&deviceGUID, lpDescription, lpName, &D3DDRVDevDesc, &D3DSWDevDesc, lpUserArg) == DDENUMRET_CANCEL)
{
return D3D_OK;
}
}
}
break;
case D3DDEVTYPE_HAL:
strcpy_s(lpName, "Direct3D HAL");
strcpy_s(lpDescription, "Microsoft Direct3D Hardware acceleration through Direct3D HAL");
if (DirectXVersion < 7)
// Get D3DSWDevDesc data (D3DDEVTYPE_REF)
ConvertDeviceDesc(D3DSWDevDesc, DeviceDesc7);

// Get D3DDRVDevDesc data (D3DDEVTYPE_HAL)
Caps9 = entry.HAL;
Caps9.DeviceType = D3DDEVTYPE_HAL;
ConvertDeviceDesc(DeviceDesc7, Caps9);
ConvertDeviceDesc(D3DDRVDevDesc, DeviceDesc7);

if (lpEnumDevicesCallback(&deviceGUID, lpDescription, lpName, &D3DDRVDevDesc, &D3DSWDevDesc, lpUserArg) == DDENUMRET_CANCEL)
{
// Get D3DDRVDevDesc data (D3DDEVTYPE_HAL)
ConvertDeviceDesc(D3DDRVDevDesc, DeviceDesc7);

// Get D3DSWDevDesc data (D3DDEVTYPE_REF)
if (SUCCEEDED(d3d9Object->GetDeviceCaps(i, D3DDEVTYPE_REF, &Caps9)))
{
Caps9.DeviceType = D3DDEVTYPE_REF;
ConvertDeviceDesc(DeviceDesc7, Caps9);
ConvertDeviceDesc(D3DSWDevDesc, DeviceDesc7);

if (lpEnumDevicesCallback(&deviceGUID, lpDescription, lpName, &D3DDRVDevDesc, &D3DSWDevDesc, lpUserArg) == DDENUMRET_CANCEL)
{
return D3D_OK;
}
}
return D3D_OK;
}
break;
default:
case D3DDEVTYPE_HAL + 0x10:
strcpy_s(lpName, "Direct3D T&L HAL");
strcpy_s(lpDescription, "Microsoft Direct3D Hardware Transform and Lighting acceleration capable device");
break;
}

if (DirectXVersion == 7)
break;
case D3DDEVTYPE_HAL:
strcpy_s(lpName, "Direct3D HAL");
strcpy_s(lpDescription, "Microsoft Direct3D Hardware acceleration through Direct3D HAL");
if (DirectXVersion < 7)
{
if (lpEnumDevicesCallback7(lpDescription, lpName, &DeviceDesc7, lpUserArg) == DDENUMRET_CANCEL)
// Get D3DDRVDevDesc data (D3DDEVTYPE_HAL)
ConvertDeviceDesc(D3DDRVDevDesc, DeviceDesc7);

// Get D3DSWDevDesc data (D3DDEVTYPE_REF)
Caps9 = entry.REF;
Caps9.DeviceType = D3DDEVTYPE_REF;
ConvertDeviceDesc(DeviceDesc7, Caps9);
ConvertDeviceDesc(D3DSWDevDesc, DeviceDesc7);

if (lpEnumDevicesCallback(&deviceGUID, lpDescription, lpName, &D3DDRVDevDesc, &D3DSWDevDesc, lpUserArg) == DDENUMRET_CANCEL)
{
return D3D_OK;
}
}
break;
default:
case D3DDEVTYPE_HAL + 0x10:
strcpy_s(lpName, "Direct3D T&L HAL");
strcpy_s(lpDescription, "Microsoft Direct3D Hardware Transform and Lighting acceleration capable device");
break;
}
else

if (DirectXVersion == 7)
{
LOG_LIMIT(100, __FUNCTION__ << " Error: failed to GetCaps!");
if (lpEnumDevicesCallback7(lpDescription, lpName, &DeviceDesc7, lpUserArg) == DDENUMRET_CANCEL)
{
return D3D_OK;
}
}
}
}
Expand Down Expand Up @@ -868,6 +885,9 @@ void m_IDirect3DX::InitDirect3D(DWORD DirectXVersion)
return;
}

// Get Cap9 cache
GetCap9Cache();

AddRef(DirectXVersion);
}

Expand Down
12 changes: 10 additions & 2 deletions ddraw/IDirect3DX.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ class m_IDirect3DX : public IUnknown, public AddressLookupTableDdrawObject
m_IDirect3D3 *WrapperInterface3;
m_IDirect3D7 *WrapperInterface7;

// Cache Cap9
struct DUALCAP9 {
D3DCAPS9 REF = {};
D3DCAPS9 HAL = {};
};
std::vector<DUALCAP9> Cap9Cache;

// Wrapper interface functions
inline REFIID GetWrapperType(DWORD DirectXVersion)
{
Expand All @@ -43,7 +50,8 @@ class m_IDirect3DX : public IUnknown, public AddressLookupTableDdrawObject
void InitDirect3D(DWORD DirectXVersion);
void ReleaseDirect3D();

// Resolution hack
// Helper functions
void GetCap9Cache();
void ResolutionHack();

public:
Expand Down Expand Up @@ -102,6 +110,6 @@ class m_IDirect3DX : public IUnknown, public AddressLookupTableDdrawObject
ULONG Release(DWORD DirectXVersion);

// Functions handling the ddraw parent interface
void SetDdrawParent(m_IDirectDrawX *ddraw) { ddrawParent = ddraw; }
void SetDdrawParent(m_IDirectDrawX *ddraw) { ddrawParent = ddraw; GetCap9Cache(); }
void ClearDdraw() { ddrawParent = nullptr; }
};

0 comments on commit 61404cc

Please sign in to comment.