From 5b49bfb89703fac79663eeb8d77070c3cd053ead Mon Sep 17 00:00:00 2001 From: Elisha Riedlinger Date: Sat, 7 Dec 2024 14:25:53 -0800 Subject: [PATCH] Force emulation for certain system memory surfaces --- Dllmain/BuildNo.rc | 2 +- ddraw/IDirectDrawSurfaceX.cpp | 7 ++++--- ddraw/IDirectDrawTypes.cpp | 23 +++++++++++++++++++++++ ddraw/IDirectDrawTypes.h | 2 ++ ddraw/IDirectDrawX.cpp | 3 +++ ddraw/Versions/IDirectDrawSurface.cpp | 13 +++++++++++++ ddraw/Versions/IDirectDrawSurface2.cpp | 13 +++++++++++++ ddraw/Versions/IDirectDrawSurface3.cpp | 13 +++++++++++++ ddraw/Versions/IDirectDrawSurface4.cpp | 13 +++++++++++++ ddraw/Versions/IDirectDrawSurface7.cpp | 13 +++++++++++++ 10 files changed, 98 insertions(+), 4 deletions(-) diff --git a/Dllmain/BuildNo.rc b/Dllmain/BuildNo.rc index f066cc8d..9553fbd3 100644 --- a/Dllmain/BuildNo.rc +++ b/Dllmain/BuildNo.rc @@ -1 +1 @@ -#define BUILD_NUMBER 7365 +#define BUILD_NUMBER 7366 diff --git a/ddraw/IDirectDrawSurfaceX.cpp b/ddraw/IDirectDrawSurfaceX.cpp index 3c89bfc4..c2fdb02b 100644 --- a/ddraw/IDirectDrawSurfaceX.cpp +++ b/ddraw/IDirectDrawSurfaceX.cpp @@ -2637,12 +2637,13 @@ HRESULT m_IDirectDrawSurfaceX::Lock2(LPRECT lpDestRect, LPDDSURFACEDESC2 lpDDSur } // If primary surface and palette surface and created via Lock() then mark as created by lock to emulate surface (eg. Diablo) - if (IsPrimarySurface() && ShouldEmulate == SC_NOT_CREATED && surfaceDesc2.dwFlags == DDSD_CAPS) + if (ShouldEmulate == SC_NOT_CREATED && !IsSurfaceTexture() && surfaceDesc2.dwBackBufferCount == 0 && (surfaceDesc2.ddsCaps.dwCaps & DDSCAPS_FLIP) == 0 && + ((surfaceDesc2.ddsCaps.dwCaps == DDSCAPS_SYSTEMMEMORY && IsDisplayResolution(surfaceDesc2.dwWidth, surfaceDesc2.dwHeight))) || + (surfaceDesc2.dwFlags == DDSD_CAPS && IsPrimarySurface())) { UpdateSurfaceDesc(); - if (surfaceDesc2.ddpfPixelFormat.dwRGBBitCount == 8 && (surfaceDesc2.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) && - surfaceDesc2.dwBackBufferCount == 0 && (surfaceDesc2.ddsCaps.dwCaps & DDSCAPS_FLIP) == 0) + if (surfaceDesc2.ddpfPixelFormat.dwRGBBitCount == 8 || surfaceDesc2.ddsCaps.dwCaps == DDSCAPS_SYSTEMMEMORY) { ShouldEmulate = SC_FORCE_EMULATED; } diff --git a/ddraw/IDirectDrawTypes.cpp b/ddraw/IDirectDrawTypes.cpp index 2e1e97f3..fde20bd6 100644 --- a/ddraw/IDirectDrawTypes.cpp +++ b/ddraw/IDirectDrawTypes.cpp @@ -16,6 +16,29 @@ #include "ddraw.h" +// For storing resolution list +std::vector> CashedDisplayResolutions; + +void AddDisplayResolution(DWORD Width, DWORD Height) +{ + if (!IsDisplayResolution(Width, Height)) + { + CashedDisplayResolutions.push_back({ Width, Height }); + } +} + +bool IsDisplayResolution(DWORD Width, DWORD Height) +{ + for (const auto& entry : CashedDisplayResolutions) + { + if (entry.first == Width && entry.second == Height) + { + return true; + } + } + return false; +} + bool DoRectsMatch(const RECT& lhs, const RECT& rhs) { return lhs.left == rhs.left && lhs.top == rhs.top && diff --git a/ddraw/IDirectDrawTypes.h b/ddraw/IDirectDrawTypes.h index c4cf947d..d08c7b4f 100644 --- a/ddraw/IDirectDrawTypes.h +++ b/ddraw/IDirectDrawTypes.h @@ -128,6 +128,8 @@ static constexpr DWORD DDS_HEADER_FLAGS_PITCH = 0x00000008; static constexpr DWORD MaxPaletteSize = 256; +void AddDisplayResolution(DWORD Width, DWORD Height); +bool IsDisplayResolution(DWORD Width, DWORD Height); bool DoRectsMatch(const RECT& lhs, const RECT& rhs); bool GetOverlappingRect(const RECT& rect1, const RECT& rect2, RECT& outOverlapRect); void ConvertSurfaceDesc(DDSURFACEDESC &Desc, DDSURFACEDESC2 &Desc2); diff --git a/ddraw/IDirectDrawX.cpp b/ddraw/IDirectDrawX.cpp index 4434162e..82b1bcf2 100644 --- a/ddraw/IDirectDrawX.cpp +++ b/ddraw/IDirectDrawX.cpp @@ -985,6 +985,9 @@ HRESULT m_IDirectDrawX::EnumDisplayModes2(DWORD dwFlags, LPDDSURFACEDESC2 lpDDSu break; } + // Add resolution to global list + AddDisplayResolution(d3ddispmode.Width, d3ddispmode.Height); + // Loop through each bit count for (DWORD bpMode : {8, 16, 32}) { diff --git a/ddraw/Versions/IDirectDrawSurface.cpp b/ddraw/Versions/IDirectDrawSurface.cpp index 4395bd5f..646a7656 100644 --- a/ddraw/Versions/IDirectDrawSurface.cpp +++ b/ddraw/Versions/IDirectDrawSurface.cpp @@ -243,6 +243,19 @@ HRESULT m_IDirectDrawSurface::GetSurfaceDesc(LPDDSURFACEDESC a) { if (!ProxyInterface) { + if (a) + { + if (a->dwSize == sizeof(DDSURFACEDESC)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC)); + a->dwSize = sizeof(DDSURFACEDESC); + } + else if (a->dwSize == sizeof(DDSURFACEDESC2)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC2)); + a->dwSize = sizeof(DDSURFACEDESC); + } + } return DDERR_INVALIDOBJECT; } return ProxyInterface->GetSurfaceDesc(a, MipMapLevel, DirectXVersion); diff --git a/ddraw/Versions/IDirectDrawSurface2.cpp b/ddraw/Versions/IDirectDrawSurface2.cpp index e7e5ef7b..e963b2fa 100644 --- a/ddraw/Versions/IDirectDrawSurface2.cpp +++ b/ddraw/Versions/IDirectDrawSurface2.cpp @@ -243,6 +243,19 @@ HRESULT m_IDirectDrawSurface2::GetSurfaceDesc(LPDDSURFACEDESC a) { if (!ProxyInterface) { + if (a) + { + if (a->dwSize == sizeof(DDSURFACEDESC)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC)); + a->dwSize = sizeof(DDSURFACEDESC); + } + else if (a->dwSize == sizeof(DDSURFACEDESC2)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC2)); + a->dwSize = sizeof(DDSURFACEDESC); + } + } return DDERR_INVALIDOBJECT; } return ProxyInterface->GetSurfaceDesc(a, MipMapLevel, DirectXVersion); diff --git a/ddraw/Versions/IDirectDrawSurface3.cpp b/ddraw/Versions/IDirectDrawSurface3.cpp index 501c0702..a5191f05 100644 --- a/ddraw/Versions/IDirectDrawSurface3.cpp +++ b/ddraw/Versions/IDirectDrawSurface3.cpp @@ -239,6 +239,19 @@ HRESULT m_IDirectDrawSurface3::GetSurfaceDesc(LPDDSURFACEDESC a) { if (!ProxyInterface) { + if (a) + { + if (a->dwSize == sizeof(DDSURFACEDESC)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC)); + a->dwSize = sizeof(DDSURFACEDESC); + } + else if (a->dwSize == sizeof(DDSURFACEDESC2)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC2)); + a->dwSize = sizeof(DDSURFACEDESC); + } + } return DDERR_INVALIDOBJECT; } return ProxyInterface->GetSurfaceDesc(a, MipMapLevel, DirectXVersion); diff --git a/ddraw/Versions/IDirectDrawSurface4.cpp b/ddraw/Versions/IDirectDrawSurface4.cpp index 72879257..c700cc0b 100644 --- a/ddraw/Versions/IDirectDrawSurface4.cpp +++ b/ddraw/Versions/IDirectDrawSurface4.cpp @@ -239,6 +239,19 @@ HRESULT m_IDirectDrawSurface4::GetSurfaceDesc(LPDDSURFACEDESC2 a) { if (!ProxyInterface) { + if (a) + { + if (a->dwSize == sizeof(DDSURFACEDESC)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC)); + a->dwSize = sizeof(DDSURFACEDESC); + } + else if (a->dwSize == sizeof(DDSURFACEDESC2)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC2)); + a->dwSize = sizeof(DDSURFACEDESC); + } + } return DDERR_INVALIDOBJECT; } return ProxyInterface->GetSurfaceDesc2(a, MipMapLevel, DirectXVersion); diff --git a/ddraw/Versions/IDirectDrawSurface7.cpp b/ddraw/Versions/IDirectDrawSurface7.cpp index a453b9bf..32a81f63 100644 --- a/ddraw/Versions/IDirectDrawSurface7.cpp +++ b/ddraw/Versions/IDirectDrawSurface7.cpp @@ -239,6 +239,19 @@ HRESULT m_IDirectDrawSurface7::GetSurfaceDesc(LPDDSURFACEDESC2 a) { if (!ProxyInterface) { + if (a) + { + if (a->dwSize == sizeof(DDSURFACEDESC)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC)); + a->dwSize = sizeof(DDSURFACEDESC); + } + else if (a->dwSize == sizeof(DDSURFACEDESC2)) + { + ZeroMemory(a, sizeof(DDSURFACEDESC2)); + a->dwSize = sizeof(DDSURFACEDESC); + } + } return DDERR_INVALIDOBJECT; } return ProxyInterface->GetSurfaceDesc2(a, MipMapLevel, DirectXVersion);