diff --git a/DDrawCompat/CompatActivateAppHandler.h b/DDrawCompat/CompatActivateAppHandler.h deleted file mode 100644 index 370e366..0000000 --- a/DDrawCompat/CompatActivateAppHandler.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#define CINTERFACE -#define WIN32_LEAN_AND_MEAN - -#include -#include - -#include "CompatWeakPtr.h" - -namespace CompatActivateAppHandler -{ - void installHooks(); - bool isActive(); - void setFullScreenCooperativeLevel(CompatWeakPtr dd, HWND hwnd, DWORD flags); - void uninstallHooks(); -} diff --git a/DDrawCompat/CompatDirectDraw.cpp b/DDrawCompat/CompatDirectDraw.cpp deleted file mode 100644 index 9094814..0000000 --- a/DDrawCompat/CompatDirectDraw.cpp +++ /dev/null @@ -1,223 +0,0 @@ -#include "CompatActivateAppHandler.h" -#include "CompatDirectDraw.h" -#include "CompatDirectDrawSurface.h" -#include "CompatDisplayMode.h" -#include "CompatPtr.h" -#include "CompatRef.h" -#include "IReleaseNotifier.h" - -namespace -{ - struct DirectDrawInterface - { - void* vtable; - void* ddObject; - DirectDrawInterface* next; - DWORD refCount; - DWORD unknown1; - DWORD unknown2; - }; - - DirectDrawInterface* g_fullScreenDirectDraw = nullptr; - CompatWeakPtr g_fullScreenTagSurface; - - void onReleaseFullScreenTagSurface(); - - IReleaseNotifier g_fullScreenTagSurfaceReleaseNotifier(&onReleaseFullScreenTagSurface); - - CompatPtr createFullScreenTagSurface(CompatRef dd) - { - DDSURFACEDESC desc = {}; - desc.dwSize = sizeof(desc); - desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; - desc.dwWidth = 1; - desc.dwHeight = 1; - desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - - CompatPtr tagSurface; - dd->CreateSurface(&dd, &desc, &tagSurface.getRef(), nullptr); - if (tagSurface) - { - CompatPtr tagSurface7(tagSurface); - tagSurface7->SetPrivateData( - tagSurface7, IID_IReleaseNotifier, &g_fullScreenTagSurfaceReleaseNotifier, - sizeof(&g_fullScreenTagSurfaceReleaseNotifier), DDSPD_IUNKNOWNPOINTER); - } - - return tagSurface; - } - - bool isFullScreenDirectDraw(void* dd) - { - return dd && g_fullScreenDirectDraw && - static_cast(dd)->ddObject == g_fullScreenDirectDraw->ddObject; - } - - void onReleaseFullScreenTagSurface() - { - CompatActivateAppHandler::setFullScreenCooperativeLevel(nullptr, nullptr, 0); - g_fullScreenDirectDraw = nullptr; - g_fullScreenTagSurface = nullptr; - } - - void setFullScreenDirectDraw(CompatRef dd) - { - g_fullScreenTagSurface.release(); - g_fullScreenTagSurface = createFullScreenTagSurface(dd).detach(); - - /* - IDirectDraw interfaces don't conform to the COM rule about object identity: - QueryInterface with IID_IUnknown does not always return the same pointer for the same object. - The IUnknown (== IDirectDraw v1) interface may even be freed, making the interface invalid, - while the DirectDraw object itself can still be kept alive by its other interfaces. - Unfortunately, the IDirectDrawSurface GetDDInterface method inherits this problem and may - also return an invalid (already freed) interface pointer. - To work around this problem, a copy of the necessary interface data is passed - to CompatActivateAppHandler, which is sufficient for it to use QueryInterface to "safely" - obtain a valid interface pointer (other than IUnknown/IDirectDraw v1) to the full-screen - DirectDraw object. - */ - - static DirectDrawInterface fullScreenDirectDraw = {}; - ZeroMemory(&fullScreenDirectDraw, sizeof(fullScreenDirectDraw)); - DirectDrawInterface& ddIntf = reinterpret_cast(dd.get()); - fullScreenDirectDraw.vtable = ddIntf.vtable; - fullScreenDirectDraw.ddObject = ddIntf.ddObject; - g_fullScreenDirectDraw = &fullScreenDirectDraw; - } -} - -template -void CompatDirectDraw::setCompatVtable(Vtable& vtable) -{ - vtable.CreateSurface = &CreateSurface; - vtable.GetDisplayMode = &GetDisplayMode; - vtable.RestoreDisplayMode = &RestoreDisplayMode; - vtable.SetCooperativeLevel = &SetCooperativeLevel; - vtable.SetDisplayMode = &SetDisplayMode; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDraw::CreateSurface( - TDirectDraw* This, - TSurfaceDesc* lpDDSurfaceDesc, - TSurface** lplpDDSurface, - IUnknown* pUnkOuter) -{ - HRESULT result = DD_OK; - - const bool isPrimary = lpDDSurfaceDesc && - (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE); - - if (isPrimary) - { - result = CompatDirectDrawSurface::createCompatPrimarySurface( - *This, *lpDDSurfaceDesc, *lplpDDSurface); - } - else - { - if (lpDDSurfaceDesc && - (lpDDSurfaceDesc->dwFlags & DDSD_WIDTH) && - (lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT) && - !(lpDDSurfaceDesc->ddsCaps.dwCaps & (DDSCAPS_ALPHA | DDSCAPS_ZBUFFER))) - { - CompatPtr dd(Compat::queryInterface(This)); - auto dm = CompatDisplayMode::getDisplayMode(*dd); - - TSurfaceDesc desc = *lpDDSurfaceDesc; - if (!(desc.dwFlags & DDSD_PIXELFORMAT)) - { - desc.dwFlags |= DDSD_PIXELFORMAT; - desc.ddpfPixelFormat = dm.ddpfPixelFormat; - } - if (!(desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_OVERLAY | DDSCAPS_TEXTURE | - DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))) - { - desc.dwFlags |= DDSD_CAPS; - desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; - } - result = s_origVtable.CreateSurface(This, &desc, lplpDDSurface, pUnkOuter); - } - else - { - result = s_origVtable.CreateSurface(This, lpDDSurfaceDesc, lplpDDSurface, pUnkOuter); - } - } - - if (SUCCEEDED(result)) - { - CompatDirectDrawSurface::fixSurfacePtrs(**lplpDDSurface); - } - - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDraw::GetDisplayMode( - TDirectDraw* This, TSurfaceDesc* lpDDSurfaceDesc) -{ - const DWORD size = lpDDSurfaceDesc ? lpDDSurfaceDesc->dwSize : 0; - if (sizeof(DDSURFACEDESC) != size && sizeof(DDSURFACEDESC2) != size) - { - return DDERR_INVALIDPARAMS; - } - - CompatPtr dd(Compat::queryInterface(This)); - const DDSURFACEDESC2 dm = CompatDisplayMode::getDisplayMode(*dd); - CopyMemory(lpDDSurfaceDesc, &dm, size); - lpDDSurfaceDesc->dwSize = size; - - return DD_OK; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDraw::RestoreDisplayMode(TDirectDraw* This) -{ - CompatPtr dd(Compat::queryInterface(This)); - return CompatDisplayMode::restoreDisplayMode(*dd); -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDraw::SetCooperativeLevel( - TDirectDraw* This, HWND hWnd, DWORD dwFlags) -{ - if ((dwFlags & DDSCL_FULLSCREEN) && !CompatActivateAppHandler::isActive()) - { - return DDERR_EXCLUSIVEMODEALREADYSET; - } - - HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags); - if (SUCCEEDED(result)) - { - if (dwFlags & DDSCL_FULLSCREEN) - { - CompatPtr dd(Compat::queryInterface(This)); - setFullScreenDirectDraw(*dd); - CompatActivateAppHandler::setFullScreenCooperativeLevel( - reinterpret_cast(g_fullScreenDirectDraw), hWnd, dwFlags); - } - else if (isFullScreenDirectDraw(This) && g_fullScreenTagSurface) - { - g_fullScreenTagSurface.release(); - } - } - return result; -} - -template -template -HRESULT STDMETHODCALLTYPE CompatDirectDraw::SetDisplayMode( - TDirectDraw* This, - DWORD dwWidth, - DWORD dwHeight, - DWORD dwBPP, - Params... params) -{ - CompatPtr dd(Compat::queryInterface(This)); - return CompatDisplayMode::setDisplayMode(*dd, dwWidth, dwHeight, dwBPP, params...); -} - -template CompatDirectDraw; -template CompatDirectDraw; -template CompatDirectDraw; -template CompatDirectDraw; diff --git a/DDrawCompat/CompatDirectDraw.h b/DDrawCompat/CompatDirectDraw.h deleted file mode 100644 index a6886e6..0000000 --- a/DDrawCompat/CompatDirectDraw.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "CompatVtable.h" -#include "DDrawTypes.h" -#include "DirectDrawVtblVisitor.h" - -template -class CompatDirectDraw : public CompatVtable, TDirectDraw> -{ -public: - typedef typename Types::TCreatedSurface TSurface; - typedef typename Types::TSurfaceDesc TSurfaceDesc; - - static void setCompatVtable(Vtable& vtable); - - static HRESULT STDMETHODCALLTYPE CreateSurface( - TDirectDraw* This, - TSurfaceDesc* lpDDSurfaceDesc, - TSurface** lplpDDSurface, - IUnknown* pUnkOuter); - - static HRESULT STDMETHODCALLTYPE GetDisplayMode(TDirectDraw* This, TSurfaceDesc* lpDDSurfaceDesc); - static HRESULT STDMETHODCALLTYPE RestoreDisplayMode(TDirectDraw* This); - static HRESULT STDMETHODCALLTYPE SetCooperativeLevel(TDirectDraw* This, HWND hWnd, DWORD dwFlags); - - template - static HRESULT STDMETHODCALLTYPE SetDisplayMode( - TDirectDraw* This, - DWORD dwWidth, - DWORD dwHeight, - DWORD dwBPP, - Params... params); -}; diff --git a/DDrawCompat/CompatDirectDrawPalette.cpp b/DDrawCompat/CompatDirectDrawPalette.cpp deleted file mode 100644 index 833b571..0000000 --- a/DDrawCompat/CompatDirectDrawPalette.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -#include "CompatDirectDrawPalette.h" -#include "CompatPrimarySurface.h" -#include "Config.h" -#include "RealPrimarySurface.h" -#include "Time.h" - -void CompatDirectDrawPalette::setCompatVtable(IDirectDrawPaletteVtbl& vtable) -{ - vtable.SetEntries = &SetEntries; -} - -HRESULT STDMETHODCALLTYPE CompatDirectDrawPalette::SetEntries( - IDirectDrawPalette* This, - DWORD dwFlags, - DWORD dwStartingEntry, - DWORD dwCount, - LPPALETTEENTRY lpEntries) -{ - if (This == CompatPrimarySurface::g_palette) - { - waitForNextUpdate(); - if (lpEntries && dwStartingEntry + dwCount <= 256 && - 0 == std::memcmp(&CompatPrimarySurface::g_paletteEntries[dwStartingEntry], - lpEntries, dwCount * sizeof(PALETTEENTRY))) - { - return DD_OK; - } - } - - HRESULT result = s_origVtable.SetEntries(This, dwFlags, dwStartingEntry, dwCount, lpEntries); - if (This == CompatPrimarySurface::g_palette && SUCCEEDED(result)) - { - std::memcpy(&CompatPrimarySurface::g_paletteEntries[dwStartingEntry], lpEntries, - dwCount * sizeof(PALETTEENTRY)); - RealPrimarySurface::updatePalette(dwStartingEntry, dwCount); - } - return result; -} - -void CompatDirectDrawPalette::waitForNextUpdate() -{ - static std::deque updatesInLastMs; - - const long long qpcNow = Time::queryPerformanceCounter(); - const long long qpcLastMsBegin = qpcNow - Time::g_qpcFrequency / 1000; - while (!updatesInLastMs.empty() && qpcLastMsBegin - updatesInLastMs.front() > 0) - { - updatesInLastMs.pop_front(); - } - - if (updatesInLastMs.size() >= Config::maxPaletteUpdatesPerMs) - { - Sleep(1); - updatesInLastMs.clear(); - } - - updatesInLastMs.push_back(Time::queryPerformanceCounter()); -} diff --git a/DDrawCompat/CompatDirectDrawPalette.h b/DDrawCompat/CompatDirectDrawPalette.h deleted file mode 100644 index 277b93a..0000000 --- a/DDrawCompat/CompatDirectDrawPalette.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "CompatVtable.h" -#include "DirectDrawPaletteVtblVisitor.h" - -class CompatDirectDrawPalette : public CompatVtable -{ -public: - static void setCompatVtable(IDirectDrawPaletteVtbl& vtable); - - static HRESULT STDMETHODCALLTYPE SetEntries( - IDirectDrawPalette* This, - DWORD dwFlags, - DWORD dwStartingEntry, - DWORD dwCount, - LPPALETTEENTRY lpEntries); - - static void waitForNextUpdate(); -}; diff --git a/DDrawCompat/CompatDirectDrawSurface.cpp b/DDrawCompat/CompatDirectDrawSurface.cpp deleted file mode 100644 index 65a748b..0000000 --- a/DDrawCompat/CompatDirectDrawSurface.cpp +++ /dev/null @@ -1,554 +0,0 @@ -#include - -#include "CompatDirectDraw.h" -#include "CompatDirectDrawPalette.h" -#include "CompatDirectDrawSurface.h" -#include "CompatDisplayMode.h" -#include "CompatPrimarySurface.h" -#include "CompatPtr.h" -#include "DDrawProcs.h" -#include "DDrawRepository.h" -#include "Gdi/Gdi.h" -#include "IReleaseNotifier.h" -#include "RealPrimarySurface.h" - -namespace -{ - bool mirrorBlt(CompatRef dst, CompatRef src, - RECT srcRect, DWORD mirrorFx); - - bool g_lockingPrimary = false; - - void fixSurfacePtr(CompatRef surface, const DDSURFACEDESC2& desc) - { - if ((desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) || 0 == desc.dwWidth || 0 == desc.dwHeight) - { - return; - } - - DDSURFACEDESC2 tempSurfaceDesc = desc; - tempSurfaceDesc.dwWidth = 1; - tempSurfaceDesc.dwHeight = 1; - DDrawRepository::ScopedSurface tempSurface(desc); - if (!tempSurface.surface) - { - return; - } - - RECT r = { 0, 0, 1, 1 }; - surface->Blt(&surface, &r, tempSurface.surface, &r, DDBLT_WAIT, nullptr); - } - - HRESULT WINAPI fixSurfacePtrEnumCallback( - LPDIRECTDRAWSURFACE7 lpDDSurface, - LPDDSURFACEDESC2 lpDDSurfaceDesc, - LPVOID lpContext) - { - auto& visitedSurfaces = *static_cast*>(lpContext); - - CompatPtr surface(lpDDSurface); - if (visitedSurfaces.find(surface) == visitedSurfaces.end()) - { - visitedSurfaces.insert(surface); - fixSurfacePtr(*surface, *lpDDSurfaceDesc); - surface->EnumAttachedSurfaces(surface, lpContext, &fixSurfacePtrEnumCallback); - } - - return DDENUMRET_OK; - } - - void fixSurfacePtrs(CompatRef surface) - { - DDSURFACEDESC2 desc = {}; - desc.dwSize = sizeof(desc); - surface->GetSurfaceDesc(&surface, &desc); - - fixSurfacePtr(surface, desc); - std::set visitedSurfaces{ &surface }; - surface->EnumAttachedSurfaces(&surface, &visitedSurfaces, &fixSurfacePtrEnumCallback); - } - - CompatWeakPtr getMirroredSurface( - CompatRef surface, RECT* srcRect, DWORD mirrorFx) - { - DDSURFACEDESC2 desc = {}; - desc.dwSize = sizeof(desc); - HRESULT result = surface->GetSurfaceDesc(&surface, &desc); - if (FAILED(result)) - { - LOG_ONCE("Failed to get surface description for mirroring: " << result); - return nullptr; - } - - if (srcRect) - { - desc.dwWidth = srcRect->right - srcRect->left; - desc.dwHeight = srcRect->bottom - srcRect->top; - } - - DDrawRepository::ScopedSurface mirroredSurface(desc); - if (!mirroredSurface.surface) - { - return nullptr; - } - - RECT rect = { 0, 0, static_cast(desc.dwWidth), static_cast(desc.dwHeight) }; - if ((mirrorFx & DDBLTFX_MIRRORLEFTRIGHT) && (mirrorFx & DDBLTFX_MIRRORUPDOWN)) - { - DDrawRepository::Surface tempMirroredSurface = DDrawRepository::ScopedSurface(desc); - if (!tempMirroredSurface.surface || - !mirrorBlt(*tempMirroredSurface.surface, surface, srcRect ? *srcRect : rect, - DDBLTFX_MIRRORLEFTRIGHT) || - !mirrorBlt(*mirroredSurface.surface, *tempMirroredSurface.surface, rect, - DDBLTFX_MIRRORUPDOWN)) - { - return nullptr; - } - } - else if (!mirrorBlt(*mirroredSurface.surface, surface, srcRect ? *srcRect : rect, mirrorFx)) - { - return nullptr; - } - - return mirroredSurface.surface; - } - - bool mirrorBlt(CompatRef dst, CompatRef src, - RECT srcRect, DWORD mirrorFx) - { - if (DDBLTFX_MIRRORLEFTRIGHT == mirrorFx) - { - LONG width = srcRect.right - srcRect.left; - srcRect.left = srcRect.right - 1; - for (LONG x = 0; x < width; ++x) - { - HRESULT result = dst->BltFast(&dst, x, 0, &src, &srcRect, DDBLTFAST_WAIT); - if (FAILED(result)) - { - LOG_ONCE("Failed BltFast for mirroring: " << result); - return false; - } - --srcRect.left; - --srcRect.right; - } - } - else - { - LONG height = srcRect.bottom - srcRect.top; - srcRect.top = srcRect.bottom - 1; - for (LONG y = 0; y < height; ++y) - { - HRESULT result = dst->BltFast(&dst, 0, y, &src, &srcRect, DDBLTFAST_WAIT); - if (FAILED(result)) - { - LOG_ONCE("Failed BltFast for mirroring: " << result); - return false; - } - --srcRect.top; - --srcRect.bottom; - } - } - - return true; - } -} - -template -void CompatDirectDrawSurface::setCompatVtable(Vtable& vtable) -{ - vtable.Blt = &Blt; - vtable.BltFast = &BltFast; - vtable.Flip = &Flip; - vtable.GetCaps = &GetCaps; - vtable.GetSurfaceDesc = &GetSurfaceDesc; - vtable.IsLost = &IsLost; - vtable.Lock = &Lock; - vtable.QueryInterface = &QueryInterface; - vtable.ReleaseDC = &ReleaseDC; - vtable.Restore = &Restore; - vtable.SetClipper = &SetClipper; - vtable.SetPalette = &SetPalette; - vtable.Unlock = &Unlock; -} - -template -template -HRESULT CompatDirectDrawSurface::createCompatPrimarySurface( - CompatRef dd, - TSurfaceDesc compatDesc, - TSurface*& compatSurface) -{ - HRESULT result = RealPrimarySurface::create(dd); - if (FAILED(result)) - { - return result; - } - - CompatPtr dd7(Compat::queryInterface(&dd)); - const auto& dm = CompatDisplayMode::getDisplayMode(*dd7); - compatDesc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; - compatDesc.dwWidth = dm.dwWidth; - compatDesc.dwHeight = dm.dwHeight; - compatDesc.ddsCaps.dwCaps &= ~DDSCAPS_PRIMARYSURFACE; - compatDesc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; - compatDesc.ddpfPixelFormat = dm.ddpfPixelFormat; - - result = dd->CreateSurface(&dd, &compatDesc, &compatSurface, nullptr); - if (FAILED(result)) - { - Compat::Log() << "Failed to create the compat primary surface!"; - RealPrimarySurface::release(); - return result; - } - - CompatPtr primary(Compat::queryInterface(compatSurface)); - CompatPrimarySurface::setPrimary(*primary); - - return DD_OK; -} - -template -void CompatDirectDrawSurface::fixSurfacePtrs(CompatRef surface) -{ - CompatPtr surface7(Compat::queryInterface(&surface)); - ::fixSurfacePtrs(*surface7); -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Blt( - TSurface* This, - LPRECT lpDestRect, - TSurface* lpDDSrcSurface, - LPRECT lpSrcRect, - DWORD dwFlags, - LPDDBLTFX lpDDBltFx) -{ - const bool isPrimaryDest = CompatPrimarySurface::isPrimary(This); - if ((isPrimaryDest || CompatPrimarySurface::isPrimary(lpDDSrcSurface)) && - RealPrimarySurface::isLost()) - { - return DDERR_SURFACELOST; - } - - HRESULT result = DD_OK; - CompatPtr mirroredSrcSurface; - - if (lpDDSrcSurface && (dwFlags & DDBLT_DDFX) && lpDDBltFx && - (lpDDBltFx->dwDDFX & (DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN))) - { - CompatPtr srcSurface( - Compat::queryInterface(lpDDSrcSurface)); - mirroredSrcSurface.reset(Compat::queryInterface( - getMirroredSurface(*srcSurface, lpSrcRect, lpDDBltFx->dwDDFX).get())); - if (!mirroredSrcSurface) - { - LOG_ONCE("Failed to emulate a mirrored Blt"); - } - } - - if (mirroredSrcSurface) - { - DWORD flags = dwFlags; - DDBLTFX fx = *lpDDBltFx; - fx.dwDDFX &= ~(DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN); - if (0 == fx.dwDDFX) - { - flags ^= DDBLT_DDFX; - } - if (flags & DDBLT_KEYSRC) - { - DDCOLORKEY srcColorKey = {}; - s_origVtable.GetColorKey(lpDDSrcSurface, DDCKEY_SRCBLT, &srcColorKey); - s_origVtable.SetColorKey(mirroredSrcSurface, DDCKEY_SRCBLT, &srcColorKey); - } - - if (lpSrcRect) - { - RECT srcRect = { 0, 0, lpSrcRect->right - lpSrcRect->left, lpSrcRect->bottom - lpSrcRect->top }; - result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, &srcRect, flags, &fx); - } - else - { - result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, nullptr, flags, &fx); - } - } - else - { - result = s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); - } - - if (isPrimaryDest && SUCCEEDED(result)) - { - RealPrimarySurface::invalidate(lpDestRect); - RealPrimarySurface::update(); - } - - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::BltFast( - TSurface* This, - DWORD dwX, - DWORD dwY, - TSurface* lpDDSrcSurface, - LPRECT lpSrcRect, - DWORD dwTrans) -{ - const bool isPrimaryDest = CompatPrimarySurface::isPrimary(This); - if ((isPrimaryDest || CompatPrimarySurface::isPrimary(lpDDSrcSurface)) && - RealPrimarySurface::isLost()) - { - return DDERR_SURFACELOST; - } - - HRESULT result = s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); - if (isPrimaryDest && SUCCEEDED(result)) - { - const LONG x = dwX; - const LONG y = dwY; - RECT destRect = { x, y, x, y}; - if (lpSrcRect) - { - destRect.right += lpSrcRect->right - lpSrcRect->left; - destRect.bottom += lpSrcRect->bottom - lpSrcRect->top; - } - else - { - TSurfaceDesc desc = {}; - desc.dwSize = sizeof(desc); - s_origVtable.GetSurfaceDesc(lpDDSrcSurface, &desc); - destRect.right += desc.dwWidth; - destRect.bottom += desc.dwHeight; - } - RealPrimarySurface::invalidate(&destRect); - RealPrimarySurface::update(); - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Flip( - TSurface* This, - TSurface* lpDDSurfaceTargetOverride, - DWORD dwFlags) -{ - HRESULT result = s_origVtable.Flip(This, lpDDSurfaceTargetOverride, dwFlags); - if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) - { - result = RealPrimarySurface::flip(dwFlags); - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::GetCaps( - TSurface* This, - TDdsCaps* lpDDSCaps) -{ - HRESULT result = s_origVtable.GetCaps(This, lpDDSCaps); - if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) - { - restorePrimaryCaps(*lpDDSCaps); - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::GetSurfaceDesc( - TSurface* This, - TSurfaceDesc* lpDDSurfaceDesc) -{ - HRESULT result = s_origVtable.GetSurfaceDesc(This, lpDDSurfaceDesc); - if (SUCCEEDED(result) && !g_lockingPrimary && CompatPrimarySurface::isPrimary(This)) - { - restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps); - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::IsLost(TSurface* This) -{ - HRESULT result = s_origVtable.IsLost(This); - if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) - { - result = RealPrimarySurface::isLost() ? DDERR_SURFACELOST : DD_OK; - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Lock( - TSurface* This, - LPRECT lpDestRect, - TSurfaceDesc* lpDDSurfaceDesc, - DWORD dwFlags, - HANDLE hEvent) -{ - if (CompatPrimarySurface::isPrimary(This)) - { - if (RealPrimarySurface::isLost()) - { - return DDERR_SURFACELOST; - } - g_lockingPrimary = true; - } - - HRESULT result = s_origVtable.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent); - if (SUCCEEDED(result) && g_lockingPrimary && lpDDSurfaceDesc) - { - RealPrimarySurface::invalidate(lpDestRect); - restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps); - } - else if (DDERR_SURFACELOST == result) - { - TSurfaceDesc desc = {}; - desc.dwSize = sizeof(desc); - if (SUCCEEDED(s_origVtable.GetSurfaceDesc(This, &desc)) && !(desc.dwFlags & DDSD_HEIGHT)) - { - // Fixes missing handling for lost vertex buffers in Messiah - s_origVtable.Restore(This); - // Still, pass back DDERR_SURFACELOST to the application in case it handles it - } - } - - g_lockingPrimary = false; - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::QueryInterface( - TSurface* This, - REFIID riid, - LPVOID* obp) -{ - if (riid == IID_IDirectDrawGammaControl && CompatPrimarySurface::isPrimary(This)) - { - auto realPrimary(RealPrimarySurface::getSurface()); - return realPrimary->QueryInterface(realPrimary, riid, obp); - } - return s_origVtable.QueryInterface(This, riid, obp); -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::ReleaseDC(TSurface* This, HDC hDC) -{ - const bool isPrimary = CompatPrimarySurface::isPrimary(This); - if (isPrimary && RealPrimarySurface::isLost()) - { - return DDERR_SURFACELOST; - } - - HRESULT result = s_origVtable.ReleaseDC(This, hDC); - if (isPrimary && SUCCEEDED(result)) - { - RealPrimarySurface::invalidate(nullptr); - RealPrimarySurface::update(); - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Restore(TSurface* This) -{ - const bool wasLost = DDERR_SURFACELOST == s_origVtable.IsLost(This); - HRESULT result = s_origVtable.Restore(This); - if (SUCCEEDED(result)) - { - if (wasLost) - { - fixSurfacePtrs(*This); - } - if (CompatPrimarySurface::isPrimary(This)) - { - result = RealPrimarySurface::restore(); - if (wasLost) - { - Gdi::invalidate(nullptr); - } - } - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::SetClipper( - TSurface* This, - LPDIRECTDRAWCLIPPER lpDDClipper) -{ - HRESULT result = s_origVtable.SetClipper(This, lpDDClipper); - if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) - { - RealPrimarySurface::setClipper(lpDDClipper); - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::SetPalette( - TSurface* This, - LPDIRECTDRAWPALETTE lpDDPalette) -{ - const bool isPrimary = CompatPrimarySurface::isPrimary(This); - if (isPrimary) - { - if (lpDDPalette) - { - CompatDirectDrawPalette::waitForNextUpdate(); - } - if (lpDDPalette == CompatPrimarySurface::g_palette) - { - return DD_OK; - } - } - - HRESULT result = s_origVtable.SetPalette(This, lpDDPalette); - if (isPrimary && SUCCEEDED(result)) - { - CompatPrimarySurface::g_palette = lpDDPalette; - RealPrimarySurface::setPalette(); - } - return result; -} - -template -HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface::Unlock(TSurface* This, TUnlockParam lpRect) -{ - HRESULT result = s_origVtable.Unlock(This, lpRect); - if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) - { - RealPrimarySurface::update(); - } - return result; -} - -template -void CompatDirectDrawSurface::restorePrimaryCaps(TDdsCaps& caps) -{ - caps.dwCaps &= ~(DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY); - caps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM; -} - -template CompatDirectDrawSurface; -template CompatDirectDrawSurface; -template CompatDirectDrawSurface; -template CompatDirectDrawSurface; -template CompatDirectDrawSurface; - -template HRESULT CompatDirectDrawSurface::createCompatPrimarySurface( - CompatRef dd, - TSurfaceDesc compatDesc, - IDirectDrawSurface*& compatSurface); -template HRESULT CompatDirectDrawSurface::createCompatPrimarySurface( - CompatRef dd, - TSurfaceDesc compatDesc, - IDirectDrawSurface*& compatSurface); -template HRESULT CompatDirectDrawSurface::createCompatPrimarySurface( - CompatRef dd, - TSurfaceDesc compatDesc, - IDirectDrawSurface4*& compatSurface); -template HRESULT CompatDirectDrawSurface::createCompatPrimarySurface( - CompatRef dd, - TSurfaceDesc compatDesc, - IDirectDrawSurface7*& compatSurface); diff --git a/DDrawCompat/CompatDirectDrawSurface.h b/DDrawCompat/CompatDirectDrawSurface.h deleted file mode 100644 index eacad43..0000000 --- a/DDrawCompat/CompatDirectDrawSurface.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "CompatRef.h" -#include "CompatVtable.h" -#include "DDrawTypes.h" -#include "DirectDrawSurfaceVtblVisitor.h" - -template -class CompatDirectDrawSurface : public CompatVtable, TSurface> -{ -public: - typedef typename Types::TSurfaceDesc TSurfaceDesc; - typedef typename Types::TDdsCaps TDdsCaps; - typedef typename Types::TUnlockParam TUnlockParam; - - static void setCompatVtable(Vtable& vtable); - - template - static HRESULT createCompatPrimarySurface( - CompatRef dd, - TSurfaceDesc compatDesc, - TSurface*& compatSurface); - - static void fixSurfacePtrs(CompatRef surface); - - static HRESULT STDMETHODCALLTYPE Blt( - TSurface* This, - LPRECT lpDestRect, - TSurface* lpDDSrcSurface, - LPRECT lpSrcRect, - DWORD dwFlags, - LPDDBLTFX lpDDBltFx); - - static HRESULT STDMETHODCALLTYPE BltFast( - TSurface* This, - DWORD dwX, - DWORD dwY, - TSurface* lpDDSrcSurface, - LPRECT lpSrcRect, - DWORD dwTrans); - - static HRESULT STDMETHODCALLTYPE Flip( - TSurface* This, - TSurface* lpDDSurfaceTargetOverride, - DWORD dwFlags); - - static HRESULT STDMETHODCALLTYPE GetCaps(TSurface* This, TDdsCaps* lpDDSCaps); - static HRESULT STDMETHODCALLTYPE GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc); - static HRESULT STDMETHODCALLTYPE IsLost(TSurface* This); - - static HRESULT STDMETHODCALLTYPE Lock( - TSurface* This, - LPRECT lpDestRect, - TSurfaceDesc* lpDDSurfaceDesc, - DWORD dwFlags, - HANDLE hEvent); - - static HRESULT STDMETHODCALLTYPE QueryInterface(TSurface* This, REFIID riid, LPVOID* obp); - static HRESULT STDMETHODCALLTYPE ReleaseDC(TSurface* This, HDC hDC); - static HRESULT STDMETHODCALLTYPE Restore(TSurface* This); - static HRESULT STDMETHODCALLTYPE SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper); - static HRESULT STDMETHODCALLTYPE SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette); - static HRESULT STDMETHODCALLTYPE Unlock(TSurface* This, TUnlockParam lpRect); - -private: - static void restorePrimaryCaps(TDdsCaps& caps); -}; diff --git a/DDrawCompat/CompatDisplayMode.h b/DDrawCompat/CompatDisplayMode.h deleted file mode 100644 index 99dd053..0000000 --- a/DDrawCompat/CompatDisplayMode.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#define CINTERFACE - -#include - -#include "CompatRef.h" - -namespace CompatDisplayMode -{ - void installHooks(); - - HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy); - HBITMAP WINAPI createDIBitmap(HDC hdc, const BITMAPINFOHEADER* lpbmih, DWORD fdwInit, - const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage); - HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight); - - DDSURFACEDESC2 getDisplayMode(CompatRef dd); - HRESULT restoreDisplayMode(CompatRef dd); - HRESULT setDisplayMode(CompatRef dd, - DWORD width, DWORD height, DWORD bpp, DWORD refreshRate = 0, DWORD flags = 0); -}; diff --git a/DDrawCompat/CompatFontSmoothing.h b/DDrawCompat/CompatFontSmoothing.h index a416f71..df8529d 100644 --- a/DDrawCompat/CompatFontSmoothing.h +++ b/DDrawCompat/CompatFontSmoothing.h @@ -1,5 +1,9 @@ #pragma once +#define WIN32_LEAN_AND_MEAN + +#include + namespace CompatFontSmoothing { struct SystemSettings diff --git a/DDrawCompat/CompatPaletteConverter.cpp b/DDrawCompat/CompatPaletteConverter.cpp deleted file mode 100644 index 0bc19bf..0000000 --- a/DDrawCompat/CompatPaletteConverter.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include -#include - -#include "CompatDisplayMode.h" -#include "CompatPaletteConverter.h" -#include "CompatPrimarySurface.h" -#include "CompatPtr.h" -#include "DDrawRepository.h" -#include "DDrawTypes.h" -#include "Hook.h" -#include "RealPrimarySurface.h" -#include "ScopedCriticalSection.h" - -namespace -{ - HDC g_dc = nullptr; - HGDIOBJ g_oldBitmap = nullptr; - CompatWeakPtr g_surface; - - void convertPaletteEntriesToRgbQuad(RGBQUAD* entries, DWORD count) - { - for (DWORD i = 0; i < count; ++i) - { - entries[i].rgbReserved = 0; - std::swap(entries[i].rgbRed, entries[i].rgbBlue); - } - } - - HBITMAP createDibSection(const DDSURFACEDESC2& dm, void*& bits) - { - struct PalettizedBitmapInfo - { - BITMAPINFOHEADER header; - PALETTEENTRY colors[256]; - }; - - PalettizedBitmapInfo bmi = {}; - bmi.header.biSize = sizeof(bmi.header); - bmi.header.biWidth = dm.dwWidth; - bmi.header.biHeight = -static_cast(dm.dwHeight); - bmi.header.biPlanes = 1; - bmi.header.biBitCount = static_cast(dm.ddpfPixelFormat.dwRGBBitCount); - bmi.header.biCompression = BI_RGB; - - return CreateDIBSection(nullptr, reinterpret_cast(&bmi), - DIB_RGB_COLORS, &bits, nullptr, 0); - } - - CompatPtr createSurface(const DDSURFACEDESC2& dm, void* bits) - { - DDSURFACEDESC2 desc = {}; - desc.dwSize = sizeof(desc); - desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | - DDSD_PITCH | DDSD_LPSURFACE; - desc.dwWidth = dm.dwWidth; - desc.dwHeight = dm.dwHeight; - desc.ddpfPixelFormat = dm.ddpfPixelFormat; - desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - desc.lPitch = (dm.dwWidth * dm.ddpfPixelFormat.dwRGBBitCount / 8 + 3) & ~3; - desc.lpSurface = bits; - - auto dd(DDrawRepository::getDirectDraw()); - CompatPtr surface; - dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr); - return surface; - } -} - -namespace CompatPaletteConverter -{ - bool create() - { - auto dd(DDrawRepository::getDirectDraw()); - auto dm(CompatDisplayMode::getDisplayMode(*dd)); - DDSURFACEDESC2 realDm = {}; - realDm.dwSize = sizeof(realDm); - dd->GetDisplayMode(dd, &realDm); - if (dm.ddpfPixelFormat.dwRGBBitCount > 8 && - realDm.ddpfPixelFormat.dwRGBBitCount > 8) - { - return true; - } - - void* bits = nullptr; - HBITMAP dib = createDibSection(dm, bits); - if (!dib) - { - Compat::Log() << "Failed to create the palette converter DIB section"; - return false; - } - - CompatPtr surface(createSurface(dm, bits)); - if (!surface) - { - Compat::Log() << "Failed to create the palette converter surface"; - DeleteObject(dib); - return false; - } - - HDC dc = CALL_ORIG_FUNC(CreateCompatibleDC)(nullptr); - if (!dc) - { - Compat::Log() << "Failed to create the palette converter DC"; - DeleteObject(dib); - return false; - } - - g_oldBitmap = SelectObject(dc, dib); - g_dc = dc; - g_surface = surface.detach(); - return true; - } - - HDC getDc() - { - return g_dc; - } - - CompatWeakPtr getSurface() - { - return g_surface; - } - - void release() - { - if (!g_surface) - { - return; - } - - g_surface.release(); - - DeleteObject(SelectObject(g_dc, g_oldBitmap)); - DeleteDC(g_dc); - g_dc = nullptr; - } - - void setClipper(CompatWeakPtr clipper) - { - if (g_surface) - { - HRESULT result = g_surface->SetClipper(g_surface, clipper); - if (FAILED(result)) - { - LOG_ONCE("Failed to set a clipper on the palette converter surface: " << result); - } - } - } - - void updatePalette(DWORD startingEntry, DWORD count) - { - if (g_dc && CompatPrimarySurface::g_palette) - { - RGBQUAD entries[256] = {}; - std::memcpy(entries, &CompatPrimarySurface::g_paletteEntries[startingEntry], - count * sizeof(PALETTEENTRY)); - convertPaletteEntriesToRgbQuad(entries, count); - SetDIBColorTable(g_dc, startingEntry, count, entries); - } - } -}; diff --git a/DDrawCompat/CompatPaletteConverter.h b/DDrawCompat/CompatPaletteConverter.h deleted file mode 100644 index 0d867a0..0000000 --- a/DDrawCompat/CompatPaletteConverter.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#define CINTERFACE - -#include - -#include "CompatWeakPtr.h" - -namespace CompatPaletteConverter -{ - bool create(); - HDC getDc(); - CompatWeakPtr getSurface(); - void release(); - void setClipper(CompatWeakPtr clipper); - void updatePalette(DWORD startingEntry, DWORD count); -} diff --git a/DDrawCompat/CompatPrimarySurface.cpp b/DDrawCompat/CompatPrimarySurface.cpp deleted file mode 100644 index be6a0f6..0000000 --- a/DDrawCompat/CompatPrimarySurface.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -#include "CompatDirectDrawSurface.h" -#include "CompatPrimarySurface.h" -#include "CompatPtr.h" -#include "IReleaseNotifier.h" -#include "RealPrimarySurface.h" - -namespace -{ - void onRelease(); - - DDSURFACEDESC2 g_primarySurfaceDesc = {}; - CompatWeakPtr g_primarySurface = nullptr; - std::vector g_primarySurfacePtrs; - IReleaseNotifier g_releaseNotifier(onRelease); - - void onRelease() - { - Compat::LogEnter("CompatPrimarySurface::onRelease"); - - g_primarySurfacePtrs.clear(); - g_primarySurface = nullptr; - CompatPrimarySurface::g_palette = nullptr; - ZeroMemory(&CompatPrimarySurface::g_paletteEntries, sizeof(CompatPrimarySurface::g_paletteEntries)); - ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc)); - - RealPrimarySurface::release(); - - Compat::LogLeave("CompatPrimarySurface::onRelease"); - } -} - -namespace CompatPrimarySurface -{ - const DDSURFACEDESC2& getDesc() - { - return g_primarySurfaceDesc; - } - - CompatPtr getPrimary() - { - if (!g_primarySurface) - { - return nullptr; - } - return CompatPtr( - Compat::queryInterface(g_primarySurface.get())); - } - - bool isPrimary(void* surface) - { - return g_primarySurfacePtrs.end() != - std::find(g_primarySurfacePtrs.begin(), g_primarySurfacePtrs.end(), surface); - } - - void setPrimary(CompatRef surface) - { - CompatPtr surfacePtr(Compat::queryInterface(&surface)); - g_primarySurface = surfacePtr; - - ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc)); - g_primarySurfaceDesc.dwSize = sizeof(g_primarySurfaceDesc); - surface->GetSurfaceDesc(&surface, &g_primarySurfaceDesc); - - g_primarySurfacePtrs.clear(); - g_primarySurfacePtrs.push_back(&surface); - g_primarySurfacePtrs.push_back(CompatPtr(surfacePtr)); - g_primarySurfacePtrs.push_back(CompatPtr(surfacePtr)); - g_primarySurfacePtrs.push_back(CompatPtr(surfacePtr)); - g_primarySurfacePtrs.push_back(surfacePtr); - - IReleaseNotifier* releaseNotifierPtr = &g_releaseNotifier; - surface->SetPrivateData(&surface, IID_IReleaseNotifier, - releaseNotifierPtr, sizeof(releaseNotifierPtr), DDSPD_IUNKNOWNPOINTER); - } - - CompatWeakPtr g_palette; - PALETTEENTRY g_paletteEntries[256] = {}; -} diff --git a/DDrawCompat/CompatPrimarySurface.h b/DDrawCompat/CompatPrimarySurface.h deleted file mode 100644 index fb9352b..0000000 --- a/DDrawCompat/CompatPrimarySurface.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#define CINTERFACE - -#include - -#include "CompatPtr.h" -#include "CompatRef.h" - -class IReleaseNotifier; - -namespace CompatPrimarySurface -{ - const DDSURFACEDESC2& getDesc(); - CompatPtr getPrimary(); - bool isPrimary(void* surface); - void setPrimary(CompatRef surface); - - extern CompatWeakPtr g_palette; - extern PALETTEENTRY g_paletteEntries[256]; -} diff --git a/DDrawCompat/CompatActivateAppHandler.cpp b/DDrawCompat/DDraw/ActivateAppHandler.cpp similarity index 75% rename from DDrawCompat/CompatActivateAppHandler.cpp rename to DDrawCompat/DDraw/ActivateAppHandler.cpp index 1710e6d..7dad8fe 100644 --- a/DDrawCompat/CompatActivateAppHandler.cpp +++ b/DDrawCompat/DDraw/ActivateAppHandler.cpp @@ -1,11 +1,11 @@ -#include "CompatActivateAppHandler.h" -#include "CompatDirectDraw.h" -#include "CompatDirectDrawSurface.h" -#include "CompatDisplayMode.h" #include "CompatFontSmoothing.h" -#include "CompatPrimarySurface.h" #include "CompatPtr.h" #include "CompatRef.h" +#include "DDraw/ActivateAppHandler.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/DirectDraw.h" +#include "DDraw/DirectDrawSurface.h" +#include "DDraw/DisplayMode.h" #include "DDrawLog.h" #include "Gdi/Gdi.h" @@ -35,13 +35,13 @@ namespace } dd->SetCooperativeLevel(&dd, g_fullScreenCooperativeWindow, g_fullScreenCooperativeFlags); - auto dm = CompatDisplayMode::getDisplayMode(dd); + auto dm = DDraw::DisplayMode::getDisplayMode(dd); dd->SetDisplayMode(&dd, dm.dwWidth, dm.dwHeight, 32, dm.dwRefreshRate, 0); - auto primary(CompatPrimarySurface::getPrimary()); + auto primary(DDraw::CompatPrimarySurface::getPrimary()); if (primary && SUCCEEDED(primary->Restore(primary))) { - CompatDirectDrawSurface::fixSurfacePtrs(*primary); + DDraw::DirectDrawSurface::fixSurfacePtrs(*primary); Gdi::invalidate(nullptr); } @@ -115,28 +115,31 @@ namespace } } -namespace CompatActivateAppHandler +namespace DDraw { - void installHooks() + namespace ActivateAppHandler { - const DWORD threadId = GetCurrentThreadId(); - g_callWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, callWndProc, nullptr, threadId); - } + void installHooks() + { + const DWORD threadId = GetCurrentThreadId(); + g_callWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, callWndProc, nullptr, threadId); + } - bool isActive() - { - return g_isActive; - } + bool isActive() + { + return g_isActive; + } - void setFullScreenCooperativeLevel(CompatWeakPtr dd, HWND hwnd, DWORD flags) - { - g_fullScreenDirectDraw = dd; - g_fullScreenCooperativeWindow = hwnd; - g_fullScreenCooperativeFlags = flags; - } + void setFullScreenCooperativeLevel(CompatWeakPtr dd, HWND hwnd, DWORD flags) + { + g_fullScreenDirectDraw = dd; + g_fullScreenCooperativeWindow = hwnd; + g_fullScreenCooperativeFlags = flags; + } - void uninstallHooks() - { - UnhookWindowsHookEx(g_callWndProcHook); + void uninstallHooks() + { + UnhookWindowsHookEx(g_callWndProcHook); + } } } diff --git a/DDrawCompat/DDraw/ActivateAppHandler.h b/DDrawCompat/DDraw/ActivateAppHandler.h new file mode 100644 index 0000000..e220389 --- /dev/null +++ b/DDrawCompat/DDraw/ActivateAppHandler.h @@ -0,0 +1,20 @@ +#pragma once + +#define CINTERFACE +#define WIN32_LEAN_AND_MEAN + +#include +#include + +#include "CompatWeakPtr.h" + +namespace DDraw +{ + namespace ActivateAppHandler + { + void installHooks(); + bool isActive(); + void setFullScreenCooperativeLevel(CompatWeakPtr dd, HWND hwnd, DWORD flags); + void uninstallHooks(); + } +} diff --git a/DDrawCompat/DDraw/CompatPrimarySurface.cpp b/DDrawCompat/DDraw/CompatPrimarySurface.cpp new file mode 100644 index 0000000..7af9993 --- /dev/null +++ b/DDrawCompat/DDraw/CompatPrimarySurface.cpp @@ -0,0 +1,85 @@ +#include +#include + +#include "CompatPtr.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/DirectDrawSurface.h" +#include "DDraw/IReleaseNotifier.h" +#include "DDraw/RealPrimarySurface.h" + +namespace +{ + void onRelease(); + + DDSURFACEDESC2 g_primarySurfaceDesc = {}; + CompatWeakPtr g_primarySurface = nullptr; + std::vector g_primarySurfacePtrs; + DDraw::IReleaseNotifier g_releaseNotifier(onRelease); + + void onRelease() + { + Compat::LogEnter("CompatPrimarySurface::onRelease"); + + g_primarySurfacePtrs.clear(); + g_primarySurface = nullptr; + DDraw::CompatPrimarySurface::g_palette = nullptr; + ZeroMemory(&DDraw::CompatPrimarySurface::g_paletteEntries, + sizeof(DDraw::CompatPrimarySurface::g_paletteEntries)); + ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc)); + + DDraw::RealPrimarySurface::release(); + + Compat::LogLeave("CompatPrimarySurface::onRelease"); + } +} + +namespace DDraw +{ + namespace CompatPrimarySurface + { + const DDSURFACEDESC2& getDesc() + { + return g_primarySurfaceDesc; + } + + CompatPtr getPrimary() + { + if (!g_primarySurface) + { + return nullptr; + } + return CompatPtr( + Compat::queryInterface(g_primarySurface.get())); + } + + bool isPrimary(void* surface) + { + return g_primarySurfacePtrs.end() != + std::find(g_primarySurfacePtrs.begin(), g_primarySurfacePtrs.end(), surface); + } + + void setPrimary(CompatRef surface) + { + CompatPtr surfacePtr(Compat::queryInterface(&surface)); + g_primarySurface = surfacePtr; + + ZeroMemory(&g_primarySurfaceDesc, sizeof(g_primarySurfaceDesc)); + g_primarySurfaceDesc.dwSize = sizeof(g_primarySurfaceDesc); + surface->GetSurfaceDesc(&surface, &g_primarySurfaceDesc); + + g_primarySurfacePtrs.clear(); + g_primarySurfacePtrs.push_back(&surface); + g_primarySurfacePtrs.push_back(CompatPtr(surfacePtr)); + g_primarySurfacePtrs.push_back(CompatPtr(surfacePtr)); + g_primarySurfacePtrs.push_back(CompatPtr(surfacePtr)); + g_primarySurfacePtrs.push_back(surfacePtr); + + IReleaseNotifier* releaseNotifierPtr = &g_releaseNotifier; + surface->SetPrivateData(&surface, IID_IReleaseNotifier, + releaseNotifierPtr, sizeof(releaseNotifierPtr), DDSPD_IUNKNOWNPOINTER); + } + + CompatWeakPtr g_palette; + PALETTEENTRY g_paletteEntries[256] = {}; + } +} diff --git a/DDrawCompat/DDraw/CompatPrimarySurface.h b/DDrawCompat/DDraw/CompatPrimarySurface.h new file mode 100644 index 0000000..5f3920b --- /dev/null +++ b/DDrawCompat/DDraw/CompatPrimarySurface.h @@ -0,0 +1,22 @@ +#pragma once + +#define CINTERFACE + +#include + +#include "CompatPtr.h" +#include "CompatRef.h" + +namespace DDraw +{ + namespace CompatPrimarySurface + { + const DDSURFACEDESC2& getDesc(); + CompatPtr getPrimary(); + bool isPrimary(void* surface); + void setPrimary(CompatRef surface); + + extern CompatWeakPtr g_palette; + extern PALETTEENTRY g_paletteEntries[256]; + } +} diff --git a/DDrawCompat/DDraw/DirectDraw.cpp b/DDrawCompat/DDraw/DirectDraw.cpp new file mode 100644 index 0000000..7a2d580 --- /dev/null +++ b/DDrawCompat/DDraw/DirectDraw.cpp @@ -0,0 +1,226 @@ +#include "CompatPtr.h" +#include "CompatRef.h" +#include "DDraw/ActivateAppHandler.h" +#include "DDraw/DirectDraw.h" +#include "DDraw/DirectDrawSurface.h" +#include "DDraw/DisplayMode.h" +#include "DDraw/IReleaseNotifier.h" + +namespace +{ + struct DirectDrawInterface + { + void* vtable; + void* ddObject; + DirectDrawInterface* next; + DWORD refCount; + DWORD unknown1; + DWORD unknown2; + }; + + DirectDrawInterface* g_fullScreenDirectDraw = nullptr; + CompatWeakPtr g_fullScreenTagSurface; + + void onReleaseFullScreenTagSurface(); + + DDraw::IReleaseNotifier g_fullScreenTagSurfaceReleaseNotifier(&onReleaseFullScreenTagSurface); + + CompatPtr createFullScreenTagSurface(CompatRef dd) + { + DDSURFACEDESC desc = {}; + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + desc.dwWidth = 1; + desc.dwHeight = 1; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + + CompatPtr tagSurface; + dd->CreateSurface(&dd, &desc, &tagSurface.getRef(), nullptr); + if (tagSurface) + { + CompatPtr tagSurface7(tagSurface); + tagSurface7->SetPrivateData( + tagSurface7, IID_IReleaseNotifier, &g_fullScreenTagSurfaceReleaseNotifier, + sizeof(&g_fullScreenTagSurfaceReleaseNotifier), DDSPD_IUNKNOWNPOINTER); + } + + return tagSurface; + } + + bool isFullScreenDirectDraw(void* dd) + { + return dd && g_fullScreenDirectDraw && + static_cast(dd)->ddObject == g_fullScreenDirectDraw->ddObject; + } + + void onReleaseFullScreenTagSurface() + { + DDraw::ActivateAppHandler::setFullScreenCooperativeLevel(nullptr, nullptr, 0); + g_fullScreenDirectDraw = nullptr; + g_fullScreenTagSurface = nullptr; + } + + void setFullScreenDirectDraw(CompatRef dd) + { + g_fullScreenTagSurface.release(); + g_fullScreenTagSurface = createFullScreenTagSurface(dd).detach(); + + /* + IDirectDraw interfaces don't conform to the COM rule about object identity: + QueryInterface with IID_IUnknown does not always return the same pointer for the same object. + The IUnknown (== IDirectDraw v1) interface may even be freed, making the interface invalid, + while the DirectDraw object itself can still be kept alive by its other interfaces. + Unfortunately, the IDirectDrawSurface GetDDInterface method inherits this problem and may + also return an invalid (already freed) interface pointer. + To work around this problem, a copy of the necessary interface data is passed + to CompatActivateAppHandler, which is sufficient for it to use QueryInterface to "safely" + obtain a valid interface pointer (other than IUnknown/IDirectDraw v1) to the full-screen + DirectDraw object. + */ + + static DirectDrawInterface fullScreenDirectDraw = {}; + ZeroMemory(&fullScreenDirectDraw, sizeof(fullScreenDirectDraw)); + DirectDrawInterface& ddIntf = reinterpret_cast(dd.get()); + fullScreenDirectDraw.vtable = ddIntf.vtable; + fullScreenDirectDraw.ddObject = ddIntf.ddObject; + g_fullScreenDirectDraw = &fullScreenDirectDraw; + } +} + +namespace DDraw +{ + template + void DirectDraw::setCompatVtable(Vtable& vtable) + { + vtable.CreateSurface = &CreateSurface; + vtable.GetDisplayMode = &GetDisplayMode; + vtable.RestoreDisplayMode = &RestoreDisplayMode; + vtable.SetCooperativeLevel = &SetCooperativeLevel; + vtable.SetDisplayMode = &SetDisplayMode; + } + + template + HRESULT STDMETHODCALLTYPE DirectDraw::CreateSurface( + TDirectDraw* This, + TSurfaceDesc* lpDDSurfaceDesc, + TSurface** lplpDDSurface, + IUnknown* pUnkOuter) + { + HRESULT result = DD_OK; + + const bool isPrimary = lpDDSurfaceDesc && + (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE); + + if (isPrimary) + { + result = DirectDrawSurface::createCompatPrimarySurface( + *This, *lpDDSurfaceDesc, *lplpDDSurface); + } + else + { + if (lpDDSurfaceDesc && + (lpDDSurfaceDesc->dwFlags & DDSD_WIDTH) && + (lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT) && + !(lpDDSurfaceDesc->ddsCaps.dwCaps & (DDSCAPS_ALPHA | DDSCAPS_ZBUFFER))) + { + CompatPtr dd(Compat::queryInterface(This)); + auto dm = DisplayMode::getDisplayMode(*dd); + + TSurfaceDesc desc = *lpDDSurfaceDesc; + if (!(desc.dwFlags & DDSD_PIXELFORMAT)) + { + desc.dwFlags |= DDSD_PIXELFORMAT; + desc.ddpfPixelFormat = dm.ddpfPixelFormat; + } + if (!(desc.ddsCaps.dwCaps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_OVERLAY | DDSCAPS_TEXTURE | + DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER))) + { + desc.dwFlags |= DDSD_CAPS; + desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; + } + result = s_origVtable.CreateSurface(This, &desc, lplpDDSurface, pUnkOuter); + } + else + { + result = s_origVtable.CreateSurface(This, lpDDSurfaceDesc, lplpDDSurface, pUnkOuter); + } + } + + if (SUCCEEDED(result)) + { + DirectDrawSurface::fixSurfacePtrs(**lplpDDSurface); + } + + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDraw::GetDisplayMode( + TDirectDraw* This, TSurfaceDesc* lpDDSurfaceDesc) + { + const DWORD size = lpDDSurfaceDesc ? lpDDSurfaceDesc->dwSize : 0; + if (sizeof(DDSURFACEDESC) != size && sizeof(DDSURFACEDESC2) != size) + { + return DDERR_INVALIDPARAMS; + } + + CompatPtr dd(Compat::queryInterface(This)); + const DDSURFACEDESC2 dm = DisplayMode::getDisplayMode(*dd); + CopyMemory(lpDDSurfaceDesc, &dm, size); + lpDDSurfaceDesc->dwSize = size; + + return DD_OK; + } + + template + HRESULT STDMETHODCALLTYPE DirectDraw::RestoreDisplayMode(TDirectDraw* This) + { + CompatPtr dd(Compat::queryInterface(This)); + return DisplayMode::restoreDisplayMode(*dd); + } + + template + HRESULT STDMETHODCALLTYPE DirectDraw::SetCooperativeLevel( + TDirectDraw* This, HWND hWnd, DWORD dwFlags) + { + if ((dwFlags & DDSCL_FULLSCREEN) && !ActivateAppHandler::isActive()) + { + return DDERR_EXCLUSIVEMODEALREADYSET; + } + + HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags); + if (SUCCEEDED(result)) + { + if (dwFlags & DDSCL_FULLSCREEN) + { + CompatPtr dd(Compat::queryInterface(This)); + setFullScreenDirectDraw(*dd); + ActivateAppHandler::setFullScreenCooperativeLevel( + reinterpret_cast(g_fullScreenDirectDraw), hWnd, dwFlags); + } + else if (isFullScreenDirectDraw(This) && g_fullScreenTagSurface) + { + g_fullScreenTagSurface.release(); + } + } + return result; + } + + template + template + HRESULT STDMETHODCALLTYPE DirectDraw::SetDisplayMode( + TDirectDraw* This, + DWORD dwWidth, + DWORD dwHeight, + DWORD dwBPP, + Params... params) + { + CompatPtr dd(Compat::queryInterface(This)); + return DisplayMode::setDisplayMode(*dd, dwWidth, dwHeight, dwBPP, params...); + } + + template DirectDraw; + template DirectDraw; + template DirectDraw; + template DirectDraw; +} diff --git a/DDrawCompat/DDraw/DirectDraw.h b/DDrawCompat/DDraw/DirectDraw.h new file mode 100644 index 0000000..befa008 --- /dev/null +++ b/DDrawCompat/DDraw/DirectDraw.h @@ -0,0 +1,36 @@ +#pragma once + +#include "CompatVtable.h" +#include "DDraw/Types.h" +#include "DirectDrawVtblVisitor.h" + +namespace DDraw +{ + template + class DirectDraw: public CompatVtable, TDirectDraw> + { + public: + typedef typename Types::TCreatedSurface TSurface; + typedef typename Types::TSurfaceDesc TSurfaceDesc; + + static void setCompatVtable(Vtable& vtable); + + static HRESULT STDMETHODCALLTYPE CreateSurface( + TDirectDraw* This, + TSurfaceDesc* lpDDSurfaceDesc, + TSurface** lplpDDSurface, + IUnknown* pUnkOuter); + + static HRESULT STDMETHODCALLTYPE GetDisplayMode(TDirectDraw* This, TSurfaceDesc* lpDDSurfaceDesc); + static HRESULT STDMETHODCALLTYPE RestoreDisplayMode(TDirectDraw* This); + static HRESULT STDMETHODCALLTYPE SetCooperativeLevel(TDirectDraw* This, HWND hWnd, DWORD dwFlags); + + template + static HRESULT STDMETHODCALLTYPE SetDisplayMode( + TDirectDraw* This, + DWORD dwWidth, + DWORD dwHeight, + DWORD dwBPP, + Params... params); + }; +} diff --git a/DDrawCompat/DDraw/DirectDrawPalette.cpp b/DDrawCompat/DDraw/DirectDrawPalette.cpp new file mode 100644 index 0000000..381824d --- /dev/null +++ b/DDrawCompat/DDraw/DirectDrawPalette.cpp @@ -0,0 +1,64 @@ +#include +#include + +#include "Config.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/DirectDrawPalette.h" +#include "DDraw/RealPrimarySurface.h" +#include "Time.h" + +namespace DDraw +{ + void DirectDrawPalette::setCompatVtable(IDirectDrawPaletteVtbl& vtable) + { + vtable.SetEntries = &SetEntries; + } + + HRESULT STDMETHODCALLTYPE DirectDrawPalette::SetEntries( + IDirectDrawPalette* This, + DWORD dwFlags, + DWORD dwStartingEntry, + DWORD dwCount, + LPPALETTEENTRY lpEntries) + { + if (This == CompatPrimarySurface::g_palette) + { + waitForNextUpdate(); + if (lpEntries && dwStartingEntry + dwCount <= 256 && + 0 == std::memcmp(&CompatPrimarySurface::g_paletteEntries[dwStartingEntry], + lpEntries, dwCount * sizeof(PALETTEENTRY))) + { + return DD_OK; + } + } + + HRESULT result = s_origVtable.SetEntries(This, dwFlags, dwStartingEntry, dwCount, lpEntries); + if (This == CompatPrimarySurface::g_palette && SUCCEEDED(result)) + { + std::memcpy(&CompatPrimarySurface::g_paletteEntries[dwStartingEntry], lpEntries, + dwCount * sizeof(PALETTEENTRY)); + RealPrimarySurface::updatePalette(dwStartingEntry, dwCount); + } + return result; + } + + void DirectDrawPalette::waitForNextUpdate() + { + static std::deque updatesInLastMs; + + const long long qpcNow = Time::queryPerformanceCounter(); + const long long qpcLastMsBegin = qpcNow - Time::g_qpcFrequency / 1000; + while (!updatesInLastMs.empty() && qpcLastMsBegin - updatesInLastMs.front() > 0) + { + updatesInLastMs.pop_front(); + } + + if (updatesInLastMs.size() >= Config::maxPaletteUpdatesPerMs) + { + Sleep(1); + updatesInLastMs.clear(); + } + + updatesInLastMs.push_back(Time::queryPerformanceCounter()); + } +} diff --git a/DDrawCompat/DDraw/DirectDrawPalette.h b/DDrawCompat/DDraw/DirectDrawPalette.h new file mode 100644 index 0000000..4753e6c --- /dev/null +++ b/DDrawCompat/DDraw/DirectDrawPalette.h @@ -0,0 +1,22 @@ +#pragma once + +#include "CompatVtable.h" +#include "DirectDrawPaletteVtblVisitor.h" + +namespace DDraw +{ + class DirectDrawPalette : public CompatVtable + { + public: + static void setCompatVtable(IDirectDrawPaletteVtbl& vtable); + + static HRESULT STDMETHODCALLTYPE SetEntries( + IDirectDrawPalette* This, + DWORD dwFlags, + DWORD dwStartingEntry, + DWORD dwCount, + LPPALETTEENTRY lpEntries); + + static void waitForNextUpdate(); + }; +} diff --git a/DDrawCompat/DDraw/DirectDrawSurface.cpp b/DDrawCompat/DDraw/DirectDrawSurface.cpp new file mode 100644 index 0000000..896710f --- /dev/null +++ b/DDrawCompat/DDraw/DirectDrawSurface.cpp @@ -0,0 +1,558 @@ +#include + +#include "CompatPtr.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/DirectDraw.h" +#include "DDraw/DirectDrawPalette.h" +#include "DDraw/DirectDrawSurface.h" +#include "DDraw/DisplayMode.h" +#include "DDraw/IReleaseNotifier.h" +#include "DDraw/RealPrimarySurface.h" +#include "DDraw/Repository.h" +#include "DDrawProcs.h" +#include "Gdi/Gdi.h" + +namespace +{ + bool mirrorBlt(CompatRef dst, CompatRef src, + RECT srcRect, DWORD mirrorFx); + + bool g_lockingPrimary = false; + + void fixSurfacePtr(CompatRef surface, const DDSURFACEDESC2& desc) + { + if ((desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) || 0 == desc.dwWidth || 0 == desc.dwHeight) + { + return; + } + + DDSURFACEDESC2 tempSurfaceDesc = desc; + tempSurfaceDesc.dwWidth = 1; + tempSurfaceDesc.dwHeight = 1; + DDraw::Repository::ScopedSurface tempSurface(desc); + if (!tempSurface.surface) + { + return; + } + + RECT r = { 0, 0, 1, 1 }; + surface->Blt(&surface, &r, tempSurface.surface, &r, DDBLT_WAIT, nullptr); + } + + HRESULT WINAPI fixSurfacePtrEnumCallback( + LPDIRECTDRAWSURFACE7 lpDDSurface, + LPDDSURFACEDESC2 lpDDSurfaceDesc, + LPVOID lpContext) + { + auto& visitedSurfaces = *static_cast*>(lpContext); + + CompatPtr surface(lpDDSurface); + if (visitedSurfaces.find(surface) == visitedSurfaces.end()) + { + visitedSurfaces.insert(surface); + fixSurfacePtr(*surface, *lpDDSurfaceDesc); + surface->EnumAttachedSurfaces(surface, lpContext, &fixSurfacePtrEnumCallback); + } + + return DDENUMRET_OK; + } + + void fixSurfacePtrs(CompatRef surface) + { + DDSURFACEDESC2 desc = {}; + desc.dwSize = sizeof(desc); + surface->GetSurfaceDesc(&surface, &desc); + + fixSurfacePtr(surface, desc); + std::set visitedSurfaces{ &surface }; + surface->EnumAttachedSurfaces(&surface, &visitedSurfaces, &fixSurfacePtrEnumCallback); + } + + CompatWeakPtr getMirroredSurface( + CompatRef surface, RECT* srcRect, DWORD mirrorFx) + { + DDSURFACEDESC2 desc = {}; + desc.dwSize = sizeof(desc); + HRESULT result = surface->GetSurfaceDesc(&surface, &desc); + if (FAILED(result)) + { + LOG_ONCE("Failed to get surface description for mirroring: " << result); + return nullptr; + } + + if (srcRect) + { + desc.dwWidth = srcRect->right - srcRect->left; + desc.dwHeight = srcRect->bottom - srcRect->top; + } + + DDraw::Repository::ScopedSurface mirroredSurface(desc); + if (!mirroredSurface.surface) + { + return nullptr; + } + + RECT rect = { 0, 0, static_cast(desc.dwWidth), static_cast(desc.dwHeight) }; + if ((mirrorFx & DDBLTFX_MIRRORLEFTRIGHT) && (mirrorFx & DDBLTFX_MIRRORUPDOWN)) + { + DDraw::Repository::Surface tempMirroredSurface = DDraw::Repository::ScopedSurface(desc); + if (!tempMirroredSurface.surface || + !mirrorBlt(*tempMirroredSurface.surface, surface, srcRect ? *srcRect : rect, + DDBLTFX_MIRRORLEFTRIGHT) || + !mirrorBlt(*mirroredSurface.surface, *tempMirroredSurface.surface, rect, + DDBLTFX_MIRRORUPDOWN)) + { + return nullptr; + } + } + else if (!mirrorBlt(*mirroredSurface.surface, surface, srcRect ? *srcRect : rect, mirrorFx)) + { + return nullptr; + } + + return mirroredSurface.surface; + } + + bool mirrorBlt(CompatRef dst, CompatRef src, + RECT srcRect, DWORD mirrorFx) + { + if (DDBLTFX_MIRRORLEFTRIGHT == mirrorFx) + { + LONG width = srcRect.right - srcRect.left; + srcRect.left = srcRect.right - 1; + for (LONG x = 0; x < width; ++x) + { + HRESULT result = dst->BltFast(&dst, x, 0, &src, &srcRect, DDBLTFAST_WAIT); + if (FAILED(result)) + { + LOG_ONCE("Failed BltFast for mirroring: " << result); + return false; + } + --srcRect.left; + --srcRect.right; + } + } + else + { + LONG height = srcRect.bottom - srcRect.top; + srcRect.top = srcRect.bottom - 1; + for (LONG y = 0; y < height; ++y) + { + HRESULT result = dst->BltFast(&dst, 0, y, &src, &srcRect, DDBLTFAST_WAIT); + if (FAILED(result)) + { + LOG_ONCE("Failed BltFast for mirroring: " << result); + return false; + } + --srcRect.top; + --srcRect.bottom; + } + } + + return true; + } +} + +namespace DDraw +{ + template + void DirectDrawSurface::setCompatVtable(Vtable& vtable) + { + vtable.Blt = &Blt; + vtable.BltFast = &BltFast; + vtable.Flip = &Flip; + vtable.GetCaps = &GetCaps; + vtable.GetSurfaceDesc = &GetSurfaceDesc; + vtable.IsLost = &IsLost; + vtable.Lock = &Lock; + vtable.QueryInterface = &QueryInterface; + vtable.ReleaseDC = &ReleaseDC; + vtable.Restore = &Restore; + vtable.SetClipper = &SetClipper; + vtable.SetPalette = &SetPalette; + vtable.Unlock = &Unlock; + } + + template + template + HRESULT DirectDrawSurface::createCompatPrimarySurface( + CompatRef dd, + TSurfaceDesc compatDesc, + TSurface*& compatSurface) + { + HRESULT result = RealPrimarySurface::create(dd); + if (FAILED(result)) + { + return result; + } + + CompatPtr dd7(Compat::queryInterface(&dd)); + const auto& dm = DisplayMode::getDisplayMode(*dd7); + compatDesc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + compatDesc.dwWidth = dm.dwWidth; + compatDesc.dwHeight = dm.dwHeight; + compatDesc.ddsCaps.dwCaps &= ~DDSCAPS_PRIMARYSURFACE; + compatDesc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN; + compatDesc.ddpfPixelFormat = dm.ddpfPixelFormat; + + result = dd->CreateSurface(&dd, &compatDesc, &compatSurface, nullptr); + if (FAILED(result)) + { + Compat::Log() << "Failed to create the compat primary surface!"; + RealPrimarySurface::release(); + return result; + } + + CompatPtr primary(Compat::queryInterface(compatSurface)); + CompatPrimarySurface::setPrimary(*primary); + + return DD_OK; + } + + template + void DirectDrawSurface::fixSurfacePtrs(CompatRef surface) + { + CompatPtr surface7(Compat::queryInterface(&surface)); + ::fixSurfacePtrs(*surface7); + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::Blt( + TSurface* This, + LPRECT lpDestRect, + TSurface* lpDDSrcSurface, + LPRECT lpSrcRect, + DWORD dwFlags, + LPDDBLTFX lpDDBltFx) + { + const bool isPrimaryDest = CompatPrimarySurface::isPrimary(This); + if ((isPrimaryDest || CompatPrimarySurface::isPrimary(lpDDSrcSurface)) && + RealPrimarySurface::isLost()) + { + return DDERR_SURFACELOST; + } + + HRESULT result = DD_OK; + CompatPtr mirroredSrcSurface; + + if (lpDDSrcSurface && (dwFlags & DDBLT_DDFX) && lpDDBltFx && + (lpDDBltFx->dwDDFX & (DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN))) + { + CompatPtr srcSurface( + Compat::queryInterface(lpDDSrcSurface)); + mirroredSrcSurface.reset(Compat::queryInterface( + getMirroredSurface(*srcSurface, lpSrcRect, lpDDBltFx->dwDDFX).get())); + if (!mirroredSrcSurface) + { + LOG_ONCE("Failed to emulate a mirrored Blt"); + } + } + + if (mirroredSrcSurface) + { + DWORD flags = dwFlags; + DDBLTFX fx = *lpDDBltFx; + fx.dwDDFX &= ~(DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN); + if (0 == fx.dwDDFX) + { + flags ^= DDBLT_DDFX; + } + if (flags & DDBLT_KEYSRC) + { + DDCOLORKEY srcColorKey = {}; + s_origVtable.GetColorKey(lpDDSrcSurface, DDCKEY_SRCBLT, &srcColorKey); + s_origVtable.SetColorKey(mirroredSrcSurface, DDCKEY_SRCBLT, &srcColorKey); + } + + if (lpSrcRect) + { + RECT srcRect = { + 0, 0, lpSrcRect->right - lpSrcRect->left, lpSrcRect->bottom - lpSrcRect->top }; + result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, &srcRect, flags, &fx); + } + else + { + result = s_origVtable.Blt(This, lpDestRect, mirroredSrcSurface, nullptr, flags, &fx); + } + } + else + { + result = s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); + } + + if (isPrimaryDest && SUCCEEDED(result)) + { + RealPrimarySurface::invalidate(lpDestRect); + RealPrimarySurface::update(); + } + + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::BltFast( + TSurface* This, + DWORD dwX, + DWORD dwY, + TSurface* lpDDSrcSurface, + LPRECT lpSrcRect, + DWORD dwTrans) + { + const bool isPrimaryDest = CompatPrimarySurface::isPrimary(This); + if ((isPrimaryDest || CompatPrimarySurface::isPrimary(lpDDSrcSurface)) && + RealPrimarySurface::isLost()) + { + return DDERR_SURFACELOST; + } + + HRESULT result = s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans); + if (isPrimaryDest && SUCCEEDED(result)) + { + const LONG x = dwX; + const LONG y = dwY; + RECT destRect = { x, y, x, y }; + if (lpSrcRect) + { + destRect.right += lpSrcRect->right - lpSrcRect->left; + destRect.bottom += lpSrcRect->bottom - lpSrcRect->top; + } + else + { + TSurfaceDesc desc = {}; + desc.dwSize = sizeof(desc); + s_origVtable.GetSurfaceDesc(lpDDSrcSurface, &desc); + destRect.right += desc.dwWidth; + destRect.bottom += desc.dwHeight; + } + RealPrimarySurface::invalidate(&destRect); + RealPrimarySurface::update(); + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::Flip( + TSurface* This, + TSurface* lpDDSurfaceTargetOverride, + DWORD dwFlags) + { + HRESULT result = s_origVtable.Flip(This, lpDDSurfaceTargetOverride, dwFlags); + if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) + { + result = RealPrimarySurface::flip(dwFlags); + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::GetCaps( + TSurface* This, + TDdsCaps* lpDDSCaps) + { + HRESULT result = s_origVtable.GetCaps(This, lpDDSCaps); + if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) + { + restorePrimaryCaps(*lpDDSCaps); + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::GetSurfaceDesc( + TSurface* This, + TSurfaceDesc* lpDDSurfaceDesc) + { + HRESULT result = s_origVtable.GetSurfaceDesc(This, lpDDSurfaceDesc); + if (SUCCEEDED(result) && !g_lockingPrimary && CompatPrimarySurface::isPrimary(This)) + { + restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps); + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::IsLost(TSurface* This) + { + HRESULT result = s_origVtable.IsLost(This); + if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) + { + result = RealPrimarySurface::isLost() ? DDERR_SURFACELOST : DD_OK; + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::Lock( + TSurface* This, + LPRECT lpDestRect, + TSurfaceDesc* lpDDSurfaceDesc, + DWORD dwFlags, + HANDLE hEvent) + { + if (CompatPrimarySurface::isPrimary(This)) + { + if (RealPrimarySurface::isLost()) + { + return DDERR_SURFACELOST; + } + g_lockingPrimary = true; + } + + HRESULT result = s_origVtable.Lock(This, lpDestRect, lpDDSurfaceDesc, dwFlags, hEvent); + if (SUCCEEDED(result) && g_lockingPrimary && lpDDSurfaceDesc) + { + RealPrimarySurface::invalidate(lpDestRect); + restorePrimaryCaps(lpDDSurfaceDesc->ddsCaps); + } + else if (DDERR_SURFACELOST == result) + { + TSurfaceDesc desc = {}; + desc.dwSize = sizeof(desc); + if (SUCCEEDED(s_origVtable.GetSurfaceDesc(This, &desc)) && !(desc.dwFlags & DDSD_HEIGHT)) + { + // Fixes missing handling for lost vertex buffers in Messiah + s_origVtable.Restore(This); + // Still, pass back DDERR_SURFACELOST to the application in case it handles it + } + } + + g_lockingPrimary = false; + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::QueryInterface( + TSurface* This, + REFIID riid, + LPVOID* obp) + { + if (riid == IID_IDirectDrawGammaControl && CompatPrimarySurface::isPrimary(This)) + { + auto realPrimary(RealPrimarySurface::getSurface()); + return realPrimary->QueryInterface(realPrimary, riid, obp); + } + return s_origVtable.QueryInterface(This, riid, obp); + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::ReleaseDC(TSurface* This, HDC hDC) + { + const bool isPrimary = CompatPrimarySurface::isPrimary(This); + if (isPrimary && RealPrimarySurface::isLost()) + { + return DDERR_SURFACELOST; + } + + HRESULT result = s_origVtable.ReleaseDC(This, hDC); + if (isPrimary && SUCCEEDED(result)) + { + RealPrimarySurface::invalidate(nullptr); + RealPrimarySurface::update(); + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::Restore(TSurface* This) + { + const bool wasLost = DDERR_SURFACELOST == s_origVtable.IsLost(This); + HRESULT result = s_origVtable.Restore(This); + if (SUCCEEDED(result)) + { + if (wasLost) + { + fixSurfacePtrs(*This); + } + if (CompatPrimarySurface::isPrimary(This)) + { + result = RealPrimarySurface::restore(); + if (wasLost) + { + Gdi::invalidate(nullptr); + } + } + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::SetClipper( + TSurface* This, + LPDIRECTDRAWCLIPPER lpDDClipper) + { + HRESULT result = s_origVtable.SetClipper(This, lpDDClipper); + if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) + { + RealPrimarySurface::setClipper(lpDDClipper); + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::SetPalette( + TSurface* This, + LPDIRECTDRAWPALETTE lpDDPalette) + { + const bool isPrimary = CompatPrimarySurface::isPrimary(This); + if (isPrimary) + { + if (lpDDPalette) + { + DirectDrawPalette::waitForNextUpdate(); + } + if (lpDDPalette == CompatPrimarySurface::g_palette) + { + return DD_OK; + } + } + + HRESULT result = s_origVtable.SetPalette(This, lpDDPalette); + if (isPrimary && SUCCEEDED(result)) + { + CompatPrimarySurface::g_palette = lpDDPalette; + RealPrimarySurface::setPalette(); + } + return result; + } + + template + HRESULT STDMETHODCALLTYPE DirectDrawSurface::Unlock(TSurface* This, TUnlockParam lpRect) + { + HRESULT result = s_origVtable.Unlock(This, lpRect); + if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This)) + { + RealPrimarySurface::update(); + } + return result; + } + + template + void DirectDrawSurface::restorePrimaryCaps(TDdsCaps& caps) + { + caps.dwCaps &= ~(DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY); + caps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM; + } + + template DirectDrawSurface; + template DirectDrawSurface; + template DirectDrawSurface; + template DirectDrawSurface; + template DirectDrawSurface; + + template HRESULT DirectDrawSurface::createCompatPrimarySurface( + CompatRef dd, + TSurfaceDesc compatDesc, + IDirectDrawSurface*& compatSurface); + template HRESULT DirectDrawSurface::createCompatPrimarySurface( + CompatRef dd, + TSurfaceDesc compatDesc, + IDirectDrawSurface*& compatSurface); + template HRESULT DirectDrawSurface::createCompatPrimarySurface( + CompatRef dd, + TSurfaceDesc compatDesc, + IDirectDrawSurface4*& compatSurface); + template HRESULT DirectDrawSurface::createCompatPrimarySurface( + CompatRef dd, + TSurfaceDesc compatDesc, + IDirectDrawSurface7*& compatSurface); +} diff --git a/DDrawCompat/DDraw/DirectDrawSurface.h b/DDrawCompat/DDraw/DirectDrawSurface.h new file mode 100644 index 0000000..f4fdbc3 --- /dev/null +++ b/DDrawCompat/DDraw/DirectDrawSurface.h @@ -0,0 +1,70 @@ +#pragma once + +#include "CompatRef.h" +#include "CompatVtable.h" +#include "DDraw/Types.h" +#include "DirectDrawSurfaceVtblVisitor.h" + +namespace DDraw +{ + template + class DirectDrawSurface : public CompatVtable, TSurface> + { + public: + typedef typename Types::TSurfaceDesc TSurfaceDesc; + typedef typename Types::TDdsCaps TDdsCaps; + typedef typename Types::TUnlockParam TUnlockParam; + + static void setCompatVtable(Vtable& vtable); + + template + static HRESULT createCompatPrimarySurface( + CompatRef dd, + TSurfaceDesc compatDesc, + TSurface*& compatSurface); + + static void fixSurfacePtrs(CompatRef surface); + + static HRESULT STDMETHODCALLTYPE Blt( + TSurface* This, + LPRECT lpDestRect, + TSurface* lpDDSrcSurface, + LPRECT lpSrcRect, + DWORD dwFlags, + LPDDBLTFX lpDDBltFx); + + static HRESULT STDMETHODCALLTYPE BltFast( + TSurface* This, + DWORD dwX, + DWORD dwY, + TSurface* lpDDSrcSurface, + LPRECT lpSrcRect, + DWORD dwTrans); + + static HRESULT STDMETHODCALLTYPE Flip( + TSurface* This, + TSurface* lpDDSurfaceTargetOverride, + DWORD dwFlags); + + static HRESULT STDMETHODCALLTYPE GetCaps(TSurface* This, TDdsCaps* lpDDSCaps); + static HRESULT STDMETHODCALLTYPE GetSurfaceDesc(TSurface* This, TSurfaceDesc* lpDDSurfaceDesc); + static HRESULT STDMETHODCALLTYPE IsLost(TSurface* This); + + static HRESULT STDMETHODCALLTYPE Lock( + TSurface* This, + LPRECT lpDestRect, + TSurfaceDesc* lpDDSurfaceDesc, + DWORD dwFlags, + HANDLE hEvent); + + static HRESULT STDMETHODCALLTYPE QueryInterface(TSurface* This, REFIID riid, LPVOID* obp); + static HRESULT STDMETHODCALLTYPE ReleaseDC(TSurface* This, HDC hDC); + static HRESULT STDMETHODCALLTYPE Restore(TSurface* This); + static HRESULT STDMETHODCALLTYPE SetClipper(TSurface* This, LPDIRECTDRAWCLIPPER lpDDClipper); + static HRESULT STDMETHODCALLTYPE SetPalette(TSurface* This, LPDIRECTDRAWPALETTE lpDDPalette); + static HRESULT STDMETHODCALLTYPE Unlock(TSurface* This, TUnlockParam lpRect); + + private: + static void restorePrimaryCaps(TDdsCaps& caps); + }; +} diff --git a/DDrawCompat/CompatDisplayMode.cpp b/DDrawCompat/DDraw/DisplayMode.cpp similarity index 72% rename from DDrawCompat/CompatDisplayMode.cpp rename to DDrawCompat/DDraw/DisplayMode.cpp index beb62a8..c17c2d4 100644 --- a/DDrawCompat/CompatDisplayMode.cpp +++ b/DDrawCompat/DDraw/DisplayMode.cpp @@ -1,7 +1,7 @@ -#include "CompatDisplayMode.h" #include "CompatPtr.h" +#include "DDraw/DisplayMode.h" +#include "DDraw/Repository.h" #include "DDrawProcs.h" -#include "DDrawRepository.h" #include "Hook.h" namespace @@ -75,7 +75,7 @@ namespace desc.ddpfPixelFormat = g_emulatedDisplayMode.ddpfPixelFormat; desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; - auto dd = DDrawRepository::getDirectDraw(); + auto dd = DDraw::Repository::getDirectDraw(); CompatPtr surface; dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr); return surface; @@ -170,74 +170,77 @@ namespace } } -namespace CompatDisplayMode +namespace DDraw { - HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy) + namespace DisplayMode { - replaceDc(hdc); - return CALL_ORIG_FUNC(CreateCompatibleBitmap)(hdc, cx, cy); - } - - HBITMAP WINAPI createDIBitmap(HDC hdc, const BITMAPINFOHEADER* lpbmih, DWORD fdwInit, - const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage) - { - replaceDc(hdc); - return CALL_ORIG_FUNC(CreateDIBitmap)(hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage); - } - - HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight) - { - replaceDc(hdc); - return CALL_ORIG_FUNC(createDiscardableBitmap)(hdc, nWidth, nHeight); - } - - DDSURFACEDESC2 getDisplayMode(CompatRef dd) - { - if (0 == g_emulatedDisplayMode.dwSize) + HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy) { - g_emulatedDisplayMode = getRealDisplayMode(dd); - } - return g_emulatedDisplayMode; - } - - void installHooks() - { - HOOK_FUNCTION(user32, ChangeDisplaySettingsExA, changeDisplaySettingsExA); - HOOK_FUNCTION(user32, ChangeDisplaySettingsExW, changeDisplaySettingsExW); - } - - HRESULT restoreDisplayMode(CompatRef dd) - { - const HRESULT result = dd->RestoreDisplayMode(&dd); - if (SUCCEEDED(result)) - { - ZeroMemory(&g_emulatedDisplayMode, sizeof(g_emulatedDisplayMode)); - releaseCompatibleDc(); - } - return result; - } - - HRESULT setDisplayMode(CompatRef dd, - DWORD width, DWORD height, DWORD bpp, DWORD refreshRate, DWORD flags) - { - DDPIXELFORMAT pf = getDisplayModePixelFormat(dd, width, height, bpp); - if (0 == pf.dwSize) - { - return DDERR_INVALIDMODE; + replaceDc(hdc); + return CALL_ORIG_FUNC(CreateCompatibleBitmap)(hdc, cx, cy); } - const HRESULT result = dd->SetDisplayMode(&dd, width, height, 32, refreshRate, flags); - if (FAILED(result)) + HBITMAP WINAPI createDIBitmap(HDC hdc, const BITMAPINFOHEADER* lpbmih, DWORD fdwInit, + const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage) { - Compat::Log() << "Failed to set the display mode to " << width << "x" << height << - "x" << bpp << " (" << std::hex << result << std::dec << ')'; + replaceDc(hdc); + return CALL_ORIG_FUNC(CreateDIBitmap)(hdc, lpbmih, fdwInit, lpbInit, lpbmi, fuUsage); + } + + HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight) + { + replaceDc(hdc); + return CALL_ORIG_FUNC(createDiscardableBitmap)(hdc, nWidth, nHeight); + } + + DDSURFACEDESC2 getDisplayMode(CompatRef dd) + { + if (0 == g_emulatedDisplayMode.dwSize) + { + g_emulatedDisplayMode = getRealDisplayMode(dd); + } + return g_emulatedDisplayMode; + } + + void installHooks() + { + HOOK_FUNCTION(user32, ChangeDisplaySettingsExA, changeDisplaySettingsExA); + HOOK_FUNCTION(user32, ChangeDisplaySettingsExW, changeDisplaySettingsExW); + } + + HRESULT restoreDisplayMode(CompatRef dd) + { + const HRESULT result = dd->RestoreDisplayMode(&dd); + if (SUCCEEDED(result)) + { + ZeroMemory(&g_emulatedDisplayMode, sizeof(g_emulatedDisplayMode)); + releaseCompatibleDc(); + } return result; } - g_emulatedDisplayMode = getRealDisplayMode(dd); - g_emulatedDisplayMode.ddpfPixelFormat = pf; - updateCompatibleDc(); + HRESULT setDisplayMode(CompatRef dd, + DWORD width, DWORD height, DWORD bpp, DWORD refreshRate, DWORD flags) + { + DDPIXELFORMAT pf = getDisplayModePixelFormat(dd, width, height, bpp); + if (0 == pf.dwSize) + { + return DDERR_INVALIDMODE; + } - return DD_OK; + const HRESULT result = dd->SetDisplayMode(&dd, width, height, 32, refreshRate, flags); + if (FAILED(result)) + { + Compat::Log() << "Failed to set the display mode to " << width << "x" << height << + "x" << bpp << " (" << std::hex << result << std::dec << ')'; + return result; + } + + g_emulatedDisplayMode = getRealDisplayMode(dd); + g_emulatedDisplayMode.ddpfPixelFormat = pf; + updateCompatibleDc(); + + return DD_OK; + } } } diff --git a/DDrawCompat/DDraw/DisplayMode.h b/DDrawCompat/DDraw/DisplayMode.h new file mode 100644 index 0000000..55e6053 --- /dev/null +++ b/DDrawCompat/DDraw/DisplayMode.h @@ -0,0 +1,25 @@ +#pragma once + +#define CINTERFACE + +#include + +#include "CompatRef.h" + +namespace DDraw +{ + namespace DisplayMode + { + void installHooks(); + + HBITMAP WINAPI createCompatibleBitmap(HDC hdc, int cx, int cy); + HBITMAP WINAPI createDIBitmap(HDC hdc, const BITMAPINFOHEADER* lpbmih, DWORD fdwInit, + const void* lpbInit, const BITMAPINFO* lpbmi, UINT fuUsage); + HBITMAP WINAPI createDiscardableBitmap(HDC hdc, int nWidth, int nHeight); + + DDSURFACEDESC2 getDisplayMode(CompatRef dd); + HRESULT restoreDisplayMode(CompatRef dd); + HRESULT setDisplayMode(CompatRef dd, + DWORD width, DWORD height, DWORD bpp, DWORD refreshRate = 0, DWORD flags = 0); + }; +} diff --git a/DDrawCompat/DDrawHooks.cpp b/DDrawCompat/DDraw/Hooks.cpp similarity index 83% rename from DDrawCompat/DDrawHooks.cpp rename to DDrawCompat/DDraw/Hooks.cpp index 70d662e..274ff42 100644 --- a/DDrawCompat/DDrawHooks.cpp +++ b/DDrawCompat/DDraw/Hooks.cpp @@ -2,19 +2,19 @@ #include -#include "CompatActivateAppHandler.h" #include "CompatDirect3d.h" #include "CompatDirect3dDevice.h" -#include "CompatDirectDraw.h" -#include "CompatDirectDrawSurface.h" -#include "CompatDirectDrawPalette.h" #include "CompatPtr.h" #include "CompatRef.h" -#include "DDrawHooks.h" +#include "DDraw/ActivateAppHandler.h" +#include "DDraw/DirectDraw.h" +#include "DDraw/DirectDrawSurface.h" +#include "DDraw/DirectDrawPalette.h" +#include "DDraw/Hooks.h" +#include "DDraw/RealPrimarySurface.h" +#include "DDraw/Repository.h" #include "DDrawLog.h" #include "DDrawProcs.h" -#include "DDrawRepository.h" -#include "RealPrimarySurface.h" namespace { @@ -118,12 +118,12 @@ namespace void hookDirectDraw(CompatRef dd) { - CompatDirectDraw::s_origVtable = *(&dd)->lpVtbl; + DDraw::DirectDraw::s_origVtable = *(&dd)->lpVtbl; CompatPtr dd7(&dd); - hookVtable>(dd7); - hookVtable>(dd7); - hookVtable>(dd7); - hookVtable>(dd7); + hookVtable>(dd7); + hookVtable>(dd7); + hookVtable>(dd7); + hookVtable>(dd7); dd7.detach(); } @@ -135,7 +135,7 @@ namespace DDPCAPS_1BIT, paletteEntries, &palette.getRef(), nullptr); if (SUCCEEDED(result)) { - CompatDirectDrawPalette::hookVtable(palette.get()->lpVtbl); + DDraw::DirectDrawPalette::hookVtable(palette.get()->lpVtbl); } else { @@ -156,12 +156,12 @@ namespace HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr); if (SUCCEEDED(result)) { - CompatDirectDrawSurface::s_origVtable = *surface.get()->lpVtbl; - hookVtable>(surface); - hookVtable>(surface); - hookVtable>(surface); - hookVtable>(surface); - hookVtable>(surface); + DDraw::DirectDrawSurface::s_origVtable = *surface.get()->lpVtbl; + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); + hookVtable>(surface); } else { @@ -176,7 +176,7 @@ namespace } } -namespace DDrawHooks +namespace DDraw { void installHooks() { @@ -195,7 +195,7 @@ namespace DDrawHooks return; } - auto dd7(DDrawRepository::getDirectDraw()); + auto dd7(Repository::getDirectDraw()); if (!dd7) { Compat::Log() << "Failed to create a DirectDraw7 object for hooking"; @@ -214,12 +214,12 @@ namespace DDrawHooks hookDirect3d7(*dd7, *renderTarget7); } - CompatActivateAppHandler::installHooks(); + ActivateAppHandler::installHooks(); } void uninstallHooks() { RealPrimarySurface::removeUpdateThread(); - CompatActivateAppHandler::uninstallHooks(); + ActivateAppHandler::uninstallHooks(); } } diff --git a/DDrawCompat/DDrawHooks.h b/DDrawCompat/DDraw/Hooks.h similarity index 75% rename from DDrawCompat/DDrawHooks.h rename to DDrawCompat/DDraw/Hooks.h index e28a467..90e9735 100644 --- a/DDrawCompat/DDrawHooks.h +++ b/DDrawCompat/DDraw/Hooks.h @@ -1,6 +1,6 @@ #pragma once -namespace DDrawHooks +namespace DDraw { void installHooks(); void uninstallHooks(); diff --git a/DDrawCompat/IReleaseNotifier.cpp b/DDrawCompat/DDraw/IReleaseNotifier.cpp similarity index 83% rename from DDrawCompat/IReleaseNotifier.cpp rename to DDrawCompat/DDraw/IReleaseNotifier.cpp index 12b0576..7e64109 100644 --- a/DDrawCompat/IReleaseNotifier.cpp +++ b/DDrawCompat/DDraw/IReleaseNotifier.cpp @@ -1,4 +1,4 @@ -#include "IReleaseNotifier.h" +#include "DDraw/IReleaseNotifier.h" #include diff --git a/DDrawCompat/DDraw/IReleaseNotifier.h b/DDrawCompat/DDraw/IReleaseNotifier.h new file mode 100644 index 0000000..7d70093 --- /dev/null +++ b/DDrawCompat/DDraw/IReleaseNotifier.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include + +// {7810158A-CB51-448A-8706-443A7DF6D4ED} +DEFINE_GUID(IID_IReleaseNotifier, + 0x7810158a, 0xcb51, 0x448a, 0x87, 0x6, 0x44, 0x3a, 0x7d, 0xf6, 0xd4, 0xed); + +namespace DDraw +{ + class IReleaseNotifier + { + public: + IReleaseNotifier(const std::function& notifyHandler) + : m_notifyHandler(notifyHandler) + { + } + + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) + { + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef() + { + return 2; + } + + virtual ULONG STDMETHODCALLTYPE Release() + { + m_notifyHandler(); + return 0; + } + + private: + std::function m_notifyHandler; + }; +} diff --git a/DDrawCompat/DDraw/PaletteConverter.cpp b/DDrawCompat/DDraw/PaletteConverter.cpp new file mode 100644 index 0000000..e797ee2 --- /dev/null +++ b/DDrawCompat/DDraw/PaletteConverter.cpp @@ -0,0 +1,164 @@ +#include +#include + +#include "CompatPtr.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/DisplayMode.h" +#include "DDraw/PaletteConverter.h" +#include "DDraw/RealPrimarySurface.h" +#include "DDraw/Repository.h" +#include "DDraw/Types.h" +#include "Hook.h" +#include "ScopedCriticalSection.h" + +namespace +{ + HDC g_dc = nullptr; + HGDIOBJ g_oldBitmap = nullptr; + CompatWeakPtr g_surface; + + void convertPaletteEntriesToRgbQuad(RGBQUAD* entries, DWORD count) + { + for (DWORD i = 0; i < count; ++i) + { + entries[i].rgbReserved = 0; + std::swap(entries[i].rgbRed, entries[i].rgbBlue); + } + } + + HBITMAP createDibSection(const DDSURFACEDESC2& dm, void*& bits) + { + struct PalettizedBitmapInfo + { + BITMAPINFOHEADER header; + PALETTEENTRY colors[256]; + }; + + PalettizedBitmapInfo bmi = {}; + bmi.header.biSize = sizeof(bmi.header); + bmi.header.biWidth = dm.dwWidth; + bmi.header.biHeight = -static_cast(dm.dwHeight); + bmi.header.biPlanes = 1; + bmi.header.biBitCount = static_cast(dm.ddpfPixelFormat.dwRGBBitCount); + bmi.header.biCompression = BI_RGB; + + return CreateDIBSection(nullptr, reinterpret_cast(&bmi), + DIB_RGB_COLORS, &bits, nullptr, 0); + } + + CompatPtr createSurface(const DDSURFACEDESC2& dm, void* bits) + { + DDSURFACEDESC2 desc = {}; + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | + DDSD_PITCH | DDSD_LPSURFACE; + desc.dwWidth = dm.dwWidth; + desc.dwHeight = dm.dwHeight; + desc.ddpfPixelFormat = dm.ddpfPixelFormat; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + desc.lPitch = (dm.dwWidth * dm.ddpfPixelFormat.dwRGBBitCount / 8 + 3) & ~3; + desc.lpSurface = bits; + + auto dd(DDraw::Repository::getDirectDraw()); + CompatPtr surface; + dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr); + return surface; + } +} + +namespace DDraw +{ + namespace PaletteConverter + { + bool create() + { + auto dd(Repository::getDirectDraw()); + auto dm(DisplayMode::getDisplayMode(*dd)); + DDSURFACEDESC2 realDm = {}; + realDm.dwSize = sizeof(realDm); + dd->GetDisplayMode(dd, &realDm); + if (dm.ddpfPixelFormat.dwRGBBitCount > 8 && + realDm.ddpfPixelFormat.dwRGBBitCount > 8) + { + return true; + } + + void* bits = nullptr; + HBITMAP dib = createDibSection(dm, bits); + if (!dib) + { + Compat::Log() << "Failed to create the palette converter DIB section"; + return false; + } + + CompatPtr surface(createSurface(dm, bits)); + if (!surface) + { + Compat::Log() << "Failed to create the palette converter surface"; + DeleteObject(dib); + return false; + } + + HDC dc = CALL_ORIG_FUNC(CreateCompatibleDC)(nullptr); + if (!dc) + { + Compat::Log() << "Failed to create the palette converter DC"; + DeleteObject(dib); + return false; + } + + g_oldBitmap = SelectObject(dc, dib); + g_dc = dc; + g_surface = surface.detach(); + return true; + } + + HDC getDc() + { + return g_dc; + } + + CompatWeakPtr getSurface() + { + return g_surface; + } + + void release() + { + if (!g_surface) + { + return; + } + + g_surface.release(); + + DeleteObject(SelectObject(g_dc, g_oldBitmap)); + DeleteDC(g_dc); + g_dc = nullptr; + } + + void setClipper(CompatWeakPtr clipper) + { + if (g_surface) + { + HRESULT result = g_surface->SetClipper(g_surface, clipper); + if (FAILED(result)) + { + LOG_ONCE("Failed to set a clipper on the palette converter surface: " << result); + } + } + } + + void updatePalette(DWORD startingEntry, DWORD count) + { + if (g_dc && CompatPrimarySurface::g_palette) + { + RGBQUAD entries[256] = {}; + std::memcpy(entries, &CompatPrimarySurface::g_paletteEntries[startingEntry], + count * sizeof(PALETTEENTRY)); + convertPaletteEntriesToRgbQuad(entries, count); + SetDIBColorTable(g_dc, startingEntry, count, entries); + } + } + }; +} diff --git a/DDrawCompat/DDraw/PaletteConverter.h b/DDrawCompat/DDraw/PaletteConverter.h new file mode 100644 index 0000000..2d229a5 --- /dev/null +++ b/DDrawCompat/DDraw/PaletteConverter.h @@ -0,0 +1,20 @@ +#pragma once + +#define CINTERFACE + +#include + +#include "CompatWeakPtr.h" + +namespace DDraw +{ + namespace PaletteConverter + { + bool create(); + HDC getDc(); + CompatWeakPtr getSurface(); + void release(); + void setClipper(CompatWeakPtr clipper); + void updatePalette(DWORD startingEntry, DWORD count); + } +} diff --git a/DDrawCompat/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp similarity index 51% rename from DDrawCompat/RealPrimarySurface.cpp rename to DDrawCompat/DDraw/RealPrimarySurface.cpp index 6770d52..09d8110 100644 --- a/DDrawCompat/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -1,17 +1,17 @@ #include -#include "CompatDirectDrawSurface.h" -#include "CompatPaletteConverter.h" -#include "CompatPrimarySurface.h" #include "CompatPtr.h" #include "Config.h" -#include "DDrawScopedThreadLock.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/DirectDrawSurface.h" +#include "DDraw/IReleaseNotifier.h" +#include "DDraw/PaletteConverter.h" +#include "DDraw/RealPrimarySurface.h" +#include "DDraw/ScopedThreadLock.h" +#include "DDraw/Types.h" #include "DDrawProcs.h" -#include "DDrawTypes.h" #include "Gdi/Gdi.h" #include "Hook.h" -#include "IReleaseNotifier.h" -#include "RealPrimarySurface.h" #include "Time.h" namespace @@ -24,7 +24,7 @@ namespace CompatWeakPtr g_backBuffer; CompatWeakPtr g_clipper; DDSURFACEDESC2 g_surfaceDesc = {}; - IReleaseNotifier g_releaseNotifier(onRelease); + DDraw::IReleaseNotifier g_releaseNotifier(onRelease); bool g_stopUpdateThread = false; HANDLE g_updateThread = nullptr; @@ -47,10 +47,10 @@ namespace bool result = false; - auto primary(CompatPrimarySurface::getPrimary()); - if (CompatPrimarySurface::getDesc().ddpfPixelFormat.dwRGBBitCount <= 8) + auto primary(DDraw::CompatPrimarySurface::getPrimary()); + if (DDraw::CompatPrimarySurface::getDesc().ddpfPixelFormat.dwRGBBitCount <= 8) { - auto paletteConverter(CompatPaletteConverter::getSurface()); + auto paletteConverter(DDraw::PaletteConverter::getSurface()); paletteConverter->Blt(paletteConverter, &g_updateRect, primary, &g_updateRect, DDBLT_WAIT, nullptr); @@ -58,7 +58,7 @@ namespace dest->GetDC(&dest, &destDc); result = TRUE == CALL_ORIG_FUNC(BitBlt)(destDc, g_updateRect.left, g_updateRect.top, g_updateRect.right - g_updateRect.left, g_updateRect.bottom - g_updateRect.top, - CompatPaletteConverter::getDc(), g_updateRect.left, g_updateRect.top, SRCCOPY); + DDraw::PaletteConverter::getDc(), g_updateRect.left, g_updateRect.top, SRCCOPY); dest->ReleaseDC(&dest, destDc); if (&dest == g_frontBuffer) @@ -92,7 +92,7 @@ namespace HRESULT init(CompatPtr surface) { - if (!CompatPaletteConverter::create()) + if (!DDraw::PaletteConverter::create()) { return DDERR_GENERIC; } @@ -153,7 +153,7 @@ namespace g_backBuffer.release(); g_clipper = nullptr; g_isFullScreen = false; - CompatPaletteConverter::release(); + DDraw::PaletteConverter::release(); ZeroMemory(&g_surfaceDesc, sizeof(g_surfaceDesc)); @@ -194,7 +194,7 @@ namespace Sleep(msUntilNextUpdate); } - Compat::DDrawScopedThreadLock lock; + DDraw::ScopedThreadLock lock; const long long qpcNow = Time::queryPerformanceCounter(); const bool isTargetUpdateStillNeeded = qpcTargetNextUpdate == g_qpcNextUpdate; if (g_frontBuffer && (isTargetUpdateStillNeeded || isNextUpdateSignaledAndReady(qpcNow))) @@ -205,180 +205,183 @@ namespace } } -template -HRESULT RealPrimarySurface::create(CompatRef dd) +namespace DDraw { - typename Types::TSurfaceDesc desc = {}; - desc.dwSize = sizeof(desc); - desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; - desc.dwBackBufferCount = 2; - - CompatPtr::TCreatedSurface> surface; - HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr); - - bool isFlippable = true; - if (DDERR_NOEXCLUSIVEMODE == result) + template + HRESULT RealPrimarySurface::create(CompatRef dd) { - desc.dwFlags = DDSD_CAPS; - desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - desc.dwBackBufferCount = 0; - isFlippable = false; - result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr); + typename Types::TSurfaceDesc desc = {}; + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; + desc.dwBackBufferCount = 2; + + CompatPtr::TCreatedSurface> surface; + HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr); + + bool isFlippable = true; + if (DDERR_NOEXCLUSIVEMODE == result) + { + desc.dwFlags = DDSD_CAPS; + desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + desc.dwBackBufferCount = 0; + isFlippable = false; + result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr); + } + + if (FAILED(result)) + { + Compat::Log() << "Failed to create the real primary surface"; + return result; + } + + return init(surface); } - if (FAILED(result)) + template HRESULT RealPrimarySurface::create(CompatRef); + template HRESULT RealPrimarySurface::create(CompatRef); + template HRESULT RealPrimarySurface::create(CompatRef); + template HRESULT RealPrimarySurface::create(CompatRef); + + void RealPrimarySurface::disableUpdates() { - Compat::Log() << "Failed to create the real primary surface"; + ++g_disableUpdateCount; + ResetEvent(g_updateEvent); + } + + void RealPrimarySurface::enableUpdates() + { + if (0 == --g_disableUpdateCount) + { + update(); + } + } + + HRESULT RealPrimarySurface::flip(DWORD flags) + { + if (!g_isFullScreen) + { + return DDERR_NOTFLIPPABLE; + } + + ResetEvent(g_updateEvent); + + invalidate(nullptr); + compatBlt(*g_backBuffer); + + HRESULT result = g_frontBuffer->Flip(g_frontBuffer, nullptr, flags); + if (SUCCEEDED(result)) + { + g_qpcNextUpdate = getNextUpdateQpc( + Time::queryPerformanceCounter() + Time::msToQpc(Config::primaryUpdateDelayAfterFlip)); + SetRectEmpty(&g_updateRect); + } return result; } - return init(surface); -} - -template HRESULT RealPrimarySurface::create(CompatRef); -template HRESULT RealPrimarySurface::create(CompatRef); -template HRESULT RealPrimarySurface::create(CompatRef); -template HRESULT RealPrimarySurface::create(CompatRef); - -void RealPrimarySurface::disableUpdates() -{ - ++g_disableUpdateCount; - ResetEvent(g_updateEvent); -} - -void RealPrimarySurface::enableUpdates() -{ - if (0 == --g_disableUpdateCount) + CompatWeakPtr RealPrimarySurface::getSurface() { - update(); - } -} - -HRESULT RealPrimarySurface::flip(DWORD flags) -{ - if (!g_isFullScreen) - { - return DDERR_NOTFLIPPABLE; + return g_frontBuffer; } - ResetEvent(g_updateEvent); - - invalidate(nullptr); - compatBlt(*g_backBuffer); - - HRESULT result = g_frontBuffer->Flip(g_frontBuffer, nullptr, flags); - if (SUCCEEDED(result)) + void RealPrimarySurface::invalidate(const RECT* rect) { - g_qpcNextUpdate = getNextUpdateQpc( - Time::queryPerformanceCounter() + Time::msToQpc(Config::primaryUpdateDelayAfterFlip)); - SetRectEmpty(&g_updateRect); - } - return result; -} - -CompatWeakPtr RealPrimarySurface::getSurface() -{ - return g_frontBuffer; -} - -void RealPrimarySurface::invalidate(const RECT* rect) -{ - if (rect) - { - UnionRect(&g_updateRect, &g_updateRect, rect); - } - else - { - auto primaryDesc = CompatPrimarySurface::getDesc(); - SetRect(&g_updateRect, 0, 0, primaryDesc.dwWidth, primaryDesc.dwHeight); - } -} - -bool RealPrimarySurface::isFullScreen() -{ - return g_isFullScreen; -} - -bool RealPrimarySurface::isLost() -{ - return g_frontBuffer && DDERR_SURFACELOST == g_frontBuffer->IsLost(g_frontBuffer); -} - -void RealPrimarySurface::release() -{ - g_frontBuffer.release(); -} - -void RealPrimarySurface::removeUpdateThread() -{ - if (!g_updateThread) - { - return; - } - - g_stopUpdateThread = true; - SetEvent(g_updateEvent); - if (WAIT_OBJECT_0 != WaitForSingleObject(g_updateThread, 1000)) - { - TerminateThread(g_updateThread, 0); - Compat::Log() << "The update thread was terminated forcefully"; - } - ResetEvent(g_updateEvent); - g_stopUpdateThread = false; - g_updateThread = nullptr; -} - -HRESULT RealPrimarySurface::restore() -{ - return g_frontBuffer->Restore(g_frontBuffer); -} - -void RealPrimarySurface::setClipper(CompatWeakPtr clipper) -{ - HRESULT result = g_frontBuffer->SetClipper(g_frontBuffer, clipper); - if (FAILED(result)) - { - LOG_ONCE("Failed to set clipper on the real primary surface: " << result); - return; - } - CompatPaletteConverter::setClipper(clipper); - g_clipper = clipper; -} - -void RealPrimarySurface::setPalette() -{ - if (g_surfaceDesc.ddpfPixelFormat.dwRGBBitCount <= 8) - { - g_frontBuffer->SetPalette(g_frontBuffer, CompatPrimarySurface::g_palette); - } - - updatePalette(0, 256); -} - -void RealPrimarySurface::update() -{ - if (!IsRectEmpty(&g_updateRect) && 0 == g_disableUpdateCount && (g_isFullScreen || g_clipper)) - { - const long long qpcNow = Time::queryPerformanceCounter(); - if (Time::qpcToMs(qpcNow - g_qpcNextUpdate) >= 0) + if (rect) { - updateNow(qpcNow); + UnionRect(&g_updateRect, &g_updateRect, rect); } else { - SetEvent(g_updateEvent); + auto primaryDesc = CompatPrimarySurface::getDesc(); + SetRect(&g_updateRect, 0, 0, primaryDesc.dwWidth, primaryDesc.dwHeight); + } + } + + bool RealPrimarySurface::isFullScreen() + { + return g_isFullScreen; + } + + bool RealPrimarySurface::isLost() + { + return g_frontBuffer && DDERR_SURFACELOST == g_frontBuffer->IsLost(g_frontBuffer); + } + + void RealPrimarySurface::release() + { + g_frontBuffer.release(); + } + + void RealPrimarySurface::removeUpdateThread() + { + if (!g_updateThread) + { + return; + } + + g_stopUpdateThread = true; + SetEvent(g_updateEvent); + if (WAIT_OBJECT_0 != WaitForSingleObject(g_updateThread, 1000)) + { + TerminateThread(g_updateThread, 0); + Compat::Log() << "The update thread was terminated forcefully"; + } + ResetEvent(g_updateEvent); + g_stopUpdateThread = false; + g_updateThread = nullptr; + } + + HRESULT RealPrimarySurface::restore() + { + return g_frontBuffer->Restore(g_frontBuffer); + } + + void RealPrimarySurface::setClipper(CompatWeakPtr clipper) + { + HRESULT result = g_frontBuffer->SetClipper(g_frontBuffer, clipper); + if (FAILED(result)) + { + LOG_ONCE("Failed to set clipper on the real primary surface: " << result); + return; + } + PaletteConverter::setClipper(clipper); + g_clipper = clipper; + } + + void RealPrimarySurface::setPalette() + { + if (g_surfaceDesc.ddpfPixelFormat.dwRGBBitCount <= 8) + { + g_frontBuffer->SetPalette(g_frontBuffer, CompatPrimarySurface::g_palette); + } + + updatePalette(0, 256); + } + + void RealPrimarySurface::update() + { + if (!IsRectEmpty(&g_updateRect) && 0 == g_disableUpdateCount && (g_isFullScreen || g_clipper)) + { + const long long qpcNow = Time::queryPerformanceCounter(); + if (Time::qpcToMs(qpcNow - g_qpcNextUpdate) >= 0) + { + updateNow(qpcNow); + } + else + { + SetEvent(g_updateEvent); + } + } + } + + void RealPrimarySurface::updatePalette(DWORD startingEntry, DWORD count) + { + PaletteConverter::updatePalette(startingEntry, count); + Gdi::updatePalette(startingEntry, count); + if (CompatPrimarySurface::g_palette) + { + invalidate(nullptr); + update(); } } } - -void RealPrimarySurface::updatePalette(DWORD startingEntry, DWORD count) -{ - CompatPaletteConverter::updatePalette(startingEntry, count); - Gdi::updatePalette(startingEntry, count); - if (CompatPrimarySurface::g_palette) - { - invalidate(nullptr); - update(); - } -} diff --git a/DDrawCompat/DDraw/RealPrimarySurface.h b/DDrawCompat/DDraw/RealPrimarySurface.h new file mode 100644 index 0000000..88b259b --- /dev/null +++ b/DDrawCompat/DDraw/RealPrimarySurface.h @@ -0,0 +1,33 @@ +#pragma once + +#define CINTERFACE + +#include + +#include "CompatWeakPtr.h" +#include "CompatRef.h" + +namespace DDraw +{ + class RealPrimarySurface + { + public: + template + static HRESULT create(CompatRef dd); + + static void disableUpdates(); + static void enableUpdates(); + static HRESULT flip(DWORD flags); + static CompatWeakPtr getSurface(); + static void invalidate(const RECT* rect); + static bool isFullScreen(); + static bool isLost(); + static void release(); + static void removeUpdateThread(); + static HRESULT restore(); + static void setClipper(CompatWeakPtr clipper); + static void setPalette(); + static void update(); + static void updatePalette(DWORD startingEntry, DWORD count); + }; +} diff --git a/DDrawCompat/DDrawRepository.cpp b/DDrawCompat/DDraw/Repository.cpp similarity index 89% rename from DDrawCompat/DDrawRepository.cpp rename to DDrawCompat/DDraw/Repository.cpp index a169df9..428a257 100644 --- a/DDrawCompat/DDrawRepository.cpp +++ b/DDrawCompat/DDraw/Repository.cpp @@ -2,13 +2,13 @@ #include #include "CompatPtr.h" +#include "DDraw/Repository.h" #include "DDrawLog.h" #include "DDrawProcs.h" -#include "DDrawRepository.h" namespace { - using DDrawRepository::Surface; + using DDraw::Repository::Surface; static std::vector g_sysMemSurfaces; static std::vector g_vidMemSurfaces; @@ -55,7 +55,7 @@ namespace surface.desc.ddpfPixelFormat = pf; surface.desc.ddsCaps.dwCaps = caps; - auto dd(DDrawRepository::getDirectDraw()); + auto dd(DDraw::Repository::getDirectDraw()); dd->CreateSurface(dd, &surface.desc, &surface.surface.getRef(), nullptr); return surface; } @@ -158,21 +158,24 @@ namespace } } -namespace DDrawRepository +namespace DDraw { - ScopedSurface::ScopedSurface(const DDSURFACEDESC2& desc) - : Surface(getSurface(desc)) + namespace Repository { - } + ScopedSurface::ScopedSurface(const DDSURFACEDESC2& desc) + : Surface(getSurface(desc)) + { + } - ScopedSurface::~ScopedSurface() - { - returnSurface(*this); - } + ScopedSurface::~ScopedSurface() + { + returnSurface(*this); + } - CompatWeakPtr getDirectDraw() - { - static auto dd = new CompatPtr(createDirectDraw()); - return *dd; + CompatWeakPtr getDirectDraw() + { + static auto dd = new CompatPtr(createDirectDraw()); + return *dd; + } } } diff --git a/DDrawCompat/DDraw/Repository.h b/DDrawCompat/DDraw/Repository.h new file mode 100644 index 0000000..a951914 --- /dev/null +++ b/DDrawCompat/DDraw/Repository.h @@ -0,0 +1,28 @@ +#pragma once + +#define CINTERFACE + +#include + +#include "CompatWeakPtr.h" + +namespace DDraw +{ + namespace Repository + { + struct Surface + { + DDSURFACEDESC2 desc; + CompatWeakPtr surface; + }; + + class ScopedSurface : public Surface + { + public: + ScopedSurface(const DDSURFACEDESC2& desc); + ~ScopedSurface(); + }; + + CompatWeakPtr getDirectDraw(); + } +} diff --git a/DDrawCompat/DDraw/ScopedThreadLock.h b/DDrawCompat/DDraw/ScopedThreadLock.h new file mode 100644 index 0000000..bde9140 --- /dev/null +++ b/DDrawCompat/DDraw/ScopedThreadLock.h @@ -0,0 +1,20 @@ +#pragma once + +#include "DDrawProcs.h" + +namespace DDraw +{ + class ScopedThreadLock + { + public: + ScopedThreadLock() + { + Compat::origProcs.AcquireDDThreadLock(); + } + + ~ScopedThreadLock() + { + Compat::origProcs.ReleaseDDThreadLock(); + } + }; +} diff --git a/DDrawCompat/DDraw/Types.h b/DDrawCompat/DDraw/Types.h new file mode 100644 index 0000000..e83dde0 --- /dev/null +++ b/DDrawCompat/DDraw/Types.h @@ -0,0 +1,72 @@ +#pragma once + +#define CINTERFACE + +#include + +namespace DDraw +{ + struct Types1 + { + typedef IDirectDrawSurface TSurface; + typedef IDirectDrawSurface TCreatedSurface; + typedef DDSURFACEDESC TSurfaceDesc; + typedef DDSCAPS TDdsCaps; + typedef LPDDENUMSURFACESCALLBACK TEnumSurfacesCallbackPtr; + typedef LPVOID TUnlockParam; + }; + + struct Types2 + { + typedef IDirectDrawSurface2 TSurface; + typedef IDirectDrawSurface TCreatedSurface; + typedef DDSURFACEDESC TSurfaceDesc; + typedef DDSCAPS TDdsCaps; + typedef LPDDENUMSURFACESCALLBACK TEnumSurfacesCallbackPtr; + typedef LPVOID TUnlockParam; + }; + + struct Types3 + { + typedef IDirectDrawSurface3 TSurface; + typedef IDirectDrawSurface3 TCreatedSurface; + typedef DDSURFACEDESC TSurfaceDesc; + typedef DDSCAPS TDdsCaps; + typedef LPDDENUMSURFACESCALLBACK TEnumSurfacesCallbackPtr; + typedef LPVOID TUnlockParam; + }; + + struct Types4 + { + typedef IDirectDrawSurface4 TSurface; + typedef IDirectDrawSurface4 TCreatedSurface; + typedef DDSURFACEDESC2 TSurfaceDesc; + typedef DDSCAPS2 TDdsCaps; + typedef LPDDENUMSURFACESCALLBACK2 TEnumSurfacesCallbackPtr; + typedef LPRECT TUnlockParam; + }; + + struct Types7 + { + typedef IDirectDrawSurface7 TSurface; + typedef IDirectDrawSurface7 TCreatedSurface; + typedef DDSURFACEDESC2 TSurfaceDesc; + typedef DDSCAPS2 TDdsCaps; + typedef LPDDENUMSURFACESCALLBACK7 TEnumSurfacesCallbackPtr; + typedef LPRECT TUnlockParam; + }; + + template + struct Types; + + template <> struct Types : Types1 {}; + template <> struct Types : Types2 {}; + template <> struct Types : Types4 {}; + template <> struct Types : Types7 {}; + + template <> struct Types : Types1 {}; + template <> struct Types : Types2 {}; + template <> struct Types : Types3 {}; + template <> struct Types : Types4 {}; + template <> struct Types : Types7 {}; +} diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 0b24b64..f8cccbc 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -147,7 +147,6 @@ - @@ -155,15 +154,13 @@ - - - + @@ -171,16 +168,21 @@ - - - - - - - - + + + + + + + + + + + + + @@ -199,13 +201,10 @@ - - - @@ -213,19 +212,23 @@ - - - - - - + + + + + + + + + + + - @@ -238,9 +241,6 @@ - - - diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 8d68b3f..e1a3d99 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -19,26 +19,20 @@ {a8e1437a-7bec-4492-830a-9a0d844aa06b} + + {370ccd34-b783-421b-87fc-84ce703e851d} + + + {bcc85014-8548-43ff-902f-16bcb6a0e96b} + Header Files - - Header Files - - - Header Files - - - Header Files - Header Files - - Header Files - Header Files @@ -51,45 +45,21 @@ Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - Header Files - - Header Files - Header Files Header Files - - Header Files - - - Header Files - Header Files Header Files - - Header Files - Header Files @@ -102,9 +72,6 @@ Header Files - - Header Files - Header Files @@ -117,9 +84,6 @@ Header Files - - Header Files - Header Files @@ -189,6 +153,48 @@ Header Files\Gdi + + Header Files + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + + + Header Files\DDraw + @@ -203,45 +209,15 @@ Source Files - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - Source Files Source Files - - Source Files - - - Source Files - Source Files - - Source Files - - - Source Files - Source Files @@ -251,9 +227,6 @@ Source Files - - Source Files - Source Files @@ -305,6 +278,39 @@ Source Files\Gdi + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + + + Source Files\DDraw + diff --git a/DDrawCompat/DDrawRepository.h b/DDrawCompat/DDrawRepository.h deleted file mode 100644 index d425c0b..0000000 --- a/DDrawCompat/DDrawRepository.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#define CINTERFACE - -#include - -#include "CompatWeakPtr.h" - -namespace DDrawRepository -{ - struct Surface - { - DDSURFACEDESC2 desc; - CompatWeakPtr surface; - }; - - class ScopedSurface : public Surface - { - public: - ScopedSurface(const DDSURFACEDESC2& desc); - ~ScopedSurface(); - }; - - CompatWeakPtr getDirectDraw(); -} diff --git a/DDrawCompat/DDrawScopedThreadLock.h b/DDrawCompat/DDrawScopedThreadLock.h deleted file mode 100644 index a72898c..0000000 --- a/DDrawCompat/DDrawScopedThreadLock.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "DDrawProcs.h" - -namespace Compat -{ - class DDrawScopedThreadLock - { - public: - DDrawScopedThreadLock() - { - origProcs.AcquireDDThreadLock(); - } - - ~DDrawScopedThreadLock() - { - origProcs.ReleaseDDThreadLock(); - } - }; -} diff --git a/DDrawCompat/DDrawTypes.h b/DDrawCompat/DDrawTypes.h deleted file mode 100644 index 12217d1..0000000 --- a/DDrawCompat/DDrawTypes.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#define CINTERFACE - -#include - -struct DDrawTypes -{ - typedef IDirectDrawSurface TSurface; - typedef IDirectDrawSurface TCreatedSurface; - typedef DDSURFACEDESC TSurfaceDesc; - typedef DDSCAPS TDdsCaps; - typedef LPDDENUMSURFACESCALLBACK TEnumSurfacesCallbackPtr; - typedef LPVOID TUnlockParam; -}; - -struct DDrawTypes2 -{ - typedef IDirectDrawSurface2 TSurface; - typedef IDirectDrawSurface TCreatedSurface; - typedef DDSURFACEDESC TSurfaceDesc; - typedef DDSCAPS TDdsCaps; - typedef LPDDENUMSURFACESCALLBACK TEnumSurfacesCallbackPtr; - typedef LPVOID TUnlockParam; -}; - -struct DDrawTypes3 -{ - typedef IDirectDrawSurface3 TSurface; - typedef IDirectDrawSurface3 TCreatedSurface; - typedef DDSURFACEDESC TSurfaceDesc; - typedef DDSCAPS TDdsCaps; - typedef LPDDENUMSURFACESCALLBACK TEnumSurfacesCallbackPtr; - typedef LPVOID TUnlockParam; -}; - -struct DDrawTypes4 -{ - typedef IDirectDrawSurface4 TSurface; - typedef IDirectDrawSurface4 TCreatedSurface; - typedef DDSURFACEDESC2 TSurfaceDesc; - typedef DDSCAPS2 TDdsCaps; - typedef LPDDENUMSURFACESCALLBACK2 TEnumSurfacesCallbackPtr; - typedef LPRECT TUnlockParam; -}; - -struct DDrawTypes7 -{ - typedef IDirectDrawSurface7 TSurface; - typedef IDirectDrawSurface7 TCreatedSurface; - typedef DDSURFACEDESC2 TSurfaceDesc; - typedef DDSCAPS2 TDdsCaps; - typedef LPDDENUMSURFACESCALLBACK7 TEnumSurfacesCallbackPtr; - typedef LPRECT TUnlockParam; -}; - -template -struct Types; - -#define DD_CONCAT(x, y, ...) x##y - -#define DD_TYPES(Interface, ...) \ - template <> \ - struct Types : DD_CONCAT(DDrawTypes, __VA_ARGS__) \ - {} - -DD_TYPES(IDirectDraw); -DD_TYPES(IDirectDraw, 2); -DD_TYPES(IDirectDraw, 4); -DD_TYPES(IDirectDraw, 7); - -DD_TYPES(IDirectDrawSurface); -DD_TYPES(IDirectDrawSurface, 2); -DD_TYPES(IDirectDrawSurface, 3); -DD_TYPES(IDirectDrawSurface, 4); -DD_TYPES(IDirectDrawSurface, 7); - -#undef DD_TYPES -#undef DD_CONCAT diff --git a/DDrawCompat/DllMain.cpp b/DDrawCompat/DllMain.cpp index 2efb4a1..7213374 100644 --- a/DDrawCompat/DllMain.cpp +++ b/DDrawCompat/DllMain.cpp @@ -5,12 +5,12 @@ #include #include -#include "CompatDisplayMode.h" #include "CompatFontSmoothing.h" #include "CompatHooks.h" #include "CompatRegistry.h" #include "D3dDdiHooks.h" -#include "DDrawHooks.h" +#include "DDraw/DisplayMode.h" +#include "DDraw/Hooks.h" #include "DDrawProcs.h" #include "Gdi/Gdi.h" #include "Time.h" @@ -30,7 +30,7 @@ namespace Compat::Log() << "Installing Direct3D driver hooks"; D3dDdiHooks::installHooks(); Compat::Log() << "Installing DirectDraw hooks"; - DDrawHooks::installHooks(); + DDraw::installHooks(); Compat::Log() << "Installing GDI hooks"; Gdi::installHooks(); Compat::Log() << "Installing registry hooks"; @@ -117,7 +117,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/) SetProcessAffinityMask(GetCurrentProcess(), 1); SetThemeAppProperties(0); - CompatDisplayMode::installHooks(); + DDraw::DisplayMode::installHooks(); CompatFontSmoothing::g_origSystemSettings = CompatFontSmoothing::getSystemSettings(); CompatHooks::installHooks(); Time::init(); @@ -135,7 +135,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/) else if (fdwReason == DLL_PROCESS_DETACH) { Compat::Log() << "Detaching DDrawCompat"; - DDrawHooks::uninstallHooks(); + DDraw::uninstallHooks(); D3dDdiHooks::uninstallHooks(); Gdi::uninstallHooks(); Compat::unhookAllFunctions(); diff --git a/DDrawCompat/Gdi/DcCache.cpp b/DDrawCompat/Gdi/DcCache.cpp index 3e7f411..99e3d2e 100644 --- a/DDrawCompat/Gdi/DcCache.cpp +++ b/DDrawCompat/Gdi/DcCache.cpp @@ -1,12 +1,12 @@ #include #include -#include "CompatPrimarySurface.h" #include "CompatPtr.h" #include "Config.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/Repository.h" #include "DDrawLog.h" #include "DDrawProcs.h" -#include "DDrawRepository.h" #include "Gdi/DcCache.h" namespace @@ -55,13 +55,13 @@ namespace CompatPtr createGdiSurface() { - DDSURFACEDESC2 desc = CompatPrimarySurface::getDesc(); + DDSURFACEDESC2 desc = DDraw::CompatPrimarySurface::getDesc(); desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE; desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; desc.lPitch = g_pitch; desc.lpSurface = g_surfaceMemory; - auto dd(DDrawRepository::getDirectDraw()); + auto dd(DDraw::Repository::getDirectDraw()); CompatPtr surface; HRESULT result = dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr); if (FAILED(result)) @@ -163,7 +163,7 @@ namespace Gdi bool init() { - auto dd(DDrawRepository::getDirectDraw()); + auto dd(DDraw::Repository::getDirectDraw()); dd->CreatePalette(dd, DDPCAPS_8BIT | DDPCAPS_ALLOW256, g_paletteEntries, &g_palette.getRef(), nullptr); return nullptr != g_palette; @@ -202,15 +202,15 @@ namespace Gdi { PALETTEENTRY entries[256] = {}; std::memcpy(&entries[startingEntry], - &CompatPrimarySurface::g_paletteEntries[startingEntry], + &DDraw::CompatPrimarySurface::g_paletteEntries[startingEntry], count * sizeof(PALETTEENTRY)); for (DWORD i = startingEntry; i < startingEntry + count; ++i) { if (entries[i].peFlags & PC_RESERVED) { - entries[i] = CompatPrimarySurface::g_paletteEntries[0]; - entries[i].peFlags = CompatPrimarySurface::g_paletteEntries[i].peFlags; + entries[i] = DDraw::CompatPrimarySurface::g_paletteEntries[0]; + entries[i].peFlags = DDraw::CompatPrimarySurface::g_paletteEntries[i].peFlags; } } diff --git a/DDrawCompat/Gdi/DcFunctions.cpp b/DDrawCompat/Gdi/DcFunctions.cpp index 3e50a41..d46edb7 100644 --- a/DDrawCompat/Gdi/DcFunctions.cpp +++ b/DDrawCompat/Gdi/DcFunctions.cpp @@ -1,6 +1,6 @@ #include -#include "CompatDisplayMode.h" +#include "DDraw/DisplayMode.h" #include "DDrawLog.h" #include "Gdi/Dc.h" #include "Gdi/DcFunctions.h" @@ -225,9 +225,9 @@ namespace Gdi // Bitmap functions HOOK_GDI_DC_FUNCTION(msimg32, AlphaBlend); HOOK_GDI_DC_FUNCTION(gdi32, BitBlt); - HOOK_FUNCTION(gdi32, CreateCompatibleBitmap, CompatDisplayMode::createCompatibleBitmap); - HOOK_FUNCTION(gdi32, CreateDIBitmap, CompatDisplayMode::createDIBitmap); - HOOK_FUNCTION(gdi32, CreateDiscardableBitmap, CompatDisplayMode::createDiscardableBitmap); + HOOK_FUNCTION(gdi32, CreateCompatibleBitmap, DDraw::DisplayMode::createCompatibleBitmap); + HOOK_FUNCTION(gdi32, CreateDIBitmap, DDraw::DisplayMode::createDIBitmap); + HOOK_FUNCTION(gdi32, CreateDiscardableBitmap, DDraw::DisplayMode::createDiscardableBitmap); HOOK_GDI_DC_FUNCTION(gdi32, ExtFloodFill); HOOK_GDI_DC_FUNCTION(gdi32, GdiAlphaBlend); HOOK_GDI_DC_FUNCTION(gdi32, GdiGradientFill); diff --git a/DDrawCompat/Gdi/Gdi.cpp b/DDrawCompat/Gdi/Gdi.cpp index bc3b93e..611c701 100644 --- a/DDrawCompat/Gdi/Gdi.cpp +++ b/DDrawCompat/Gdi/Gdi.cpp @@ -1,7 +1,8 @@ #include -#include "CompatPaletteConverter.h" -#include "CompatPrimarySurface.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/PaletteConverter.h" +#include "DDraw/RealPrimarySurface.h" #include "DDrawProcs.h" #include "Gdi/Caret.h" #include "Gdi/DcCache.h" @@ -10,7 +11,6 @@ #include "Gdi/PaintHandlers.h" #include "Gdi/ScrollFunctions.h" #include "Gdi/WinProc.h" -#include "RealPrimarySurface.h" #include "ScopedCriticalSection.h" namespace @@ -58,7 +58,7 @@ namespace { DDSURFACEDESC2 desc = {}; desc.dwSize = sizeof(desc); - auto primary(CompatPrimarySurface::getPrimary()); + auto primary(DDraw::CompatPrimarySurface::getPrimary()); if (FAILED(primary->Lock(primary, nullptr, &desc, lockFlags | DDLOCK_WAIT, nullptr))) { return false; @@ -79,12 +79,12 @@ namespace void unlockPrimarySurface() { GdiFlush(); - auto primary(CompatPrimarySurface::getPrimary()); + auto primary(DDraw::CompatPrimarySurface::getPrimary()); primary->Unlock(primary, nullptr); if (DDLOCK_READONLY != g_ddLockFlags) { - RealPrimarySurface::invalidate(nullptr); - RealPrimarySurface::update(); + DDraw::RealPrimarySurface::invalidate(nullptr); + DDraw::RealPrimarySurface::update(); } if (0 != g_ddLockFlags) @@ -220,7 +220,7 @@ namespace Gdi bool isEmulationEnabled() { - return g_disableEmulationCount <= 0 && RealPrimarySurface::isFullScreen(); + return g_disableEmulationCount <= 0 && DDraw::RealPrimarySurface::isFullScreen(); } void unhookWndProc(LPCSTR className, WNDPROC oldWndProc) @@ -239,7 +239,7 @@ namespace Gdi void updatePalette(DWORD startingEntry, DWORD count) { - if (isEmulationEnabled() && CompatPrimarySurface::g_palette) + if (isEmulationEnabled() && DDraw::CompatPrimarySurface::g_palette) { Gdi::DcCache::updatePalette(startingEntry, count); } diff --git a/DDrawCompat/Gdi/PaintHandlers.cpp b/DDrawCompat/Gdi/PaintHandlers.cpp index b0ff9c6..4e8f5f9 100644 --- a/DDrawCompat/Gdi/PaintHandlers.cpp +++ b/DDrawCompat/Gdi/PaintHandlers.cpp @@ -1,5 +1,6 @@ -#include "CompatPrimarySurface.h" #include "CompatRegistry.h" +#include "DDraw/CompatPrimarySurface.h" +#include "DDraw/RealPrimarySurface.h" #include "DDrawLog.h" #include "Gdi/Dc.h" #include "Gdi/Gdi.h" @@ -8,7 +9,6 @@ #include "Gdi/ScrollFunctions.h" #include "Gdi/TitleBar.h" #include "Hook.h" -#include "RealPrimarySurface.h" namespace { @@ -170,7 +170,7 @@ namespace Gdi::Dc::releaseDc(dc); if (result) { - RealPrimarySurface::disableUpdates(); + DDraw::RealPrimarySurface::disableUpdates(); } } else @@ -183,7 +183,7 @@ namespace if (result && compatDc) { UpdateWindow(hwnd); - RealPrimarySurface::enableUpdates(); + DDraw::RealPrimarySurface::enableUpdates(); } return result; diff --git a/DDrawCompat/Gdi/ScrollFunctions.cpp b/DDrawCompat/Gdi/ScrollFunctions.cpp index 32dc50c..b19abb6 100644 --- a/DDrawCompat/Gdi/ScrollFunctions.cpp +++ b/DDrawCompat/Gdi/ScrollFunctions.cpp @@ -1,8 +1,8 @@ +#include "DDraw/RealPrimarySurface.h" #include "DDrawLog.h" #include "Gdi/Gdi.h" #include "Gdi/ScrollFunctions.h" #include "Hook.h" -#include "RealPrimarySurface.h" namespace { @@ -57,10 +57,10 @@ namespace Gdi { if (Gdi::isEmulationEnabled()) { - RealPrimarySurface::disableUpdates(); + DDraw::RealPrimarySurface::disableUpdates(); RedrawWindow(hwnd, nullptr, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW); - RealPrimarySurface::enableUpdates(); + DDraw::RealPrimarySurface::enableUpdates(); } } } diff --git a/DDrawCompat/Gdi/TitleBar.cpp b/DDrawCompat/Gdi/TitleBar.cpp index 38b5196..b6fbc04 100644 --- a/DDrawCompat/Gdi/TitleBar.cpp +++ b/DDrawCompat/Gdi/TitleBar.cpp @@ -1,4 +1,4 @@ -#include "CompatPrimarySurface.h" +#include "DDraw/CompatPrimarySurface.h" #include "Gdi/Gdi.h" #include "Gdi/TitleBar.h" #include "Hook.h" @@ -96,7 +96,7 @@ namespace Gdi { flags |= DC_ACTIVE; } - if (CompatPrimarySurface::getDesc().ddpfPixelFormat.dwRGBBitCount > 8) + if (DDraw::CompatPrimarySurface::getDesc().ddpfPixelFormat.dwRGBBitCount > 8) { flags |= DC_GRADIENT; } diff --git a/DDrawCompat/IReleaseNotifier.h b/DDrawCompat/IReleaseNotifier.h deleted file mode 100644 index d20acf2..0000000 --- a/DDrawCompat/IReleaseNotifier.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include - -#include - -// {7810158A-CB51-448A-8706-443A7DF6D4ED} -DEFINE_GUID(IID_IReleaseNotifier, - 0x7810158a, 0xcb51, 0x448a, 0x87, 0x6, 0x44, 0x3a, 0x7d, 0xf6, 0xd4, 0xed); - -class IReleaseNotifier -{ -public: - IReleaseNotifier(const std::function& notifyHandler) - : m_notifyHandler(notifyHandler) - { - } - - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) - { - return E_NOINTERFACE; - } - - virtual ULONG STDMETHODCALLTYPE AddRef() - { - return 2; - } - - virtual ULONG STDMETHODCALLTYPE Release() - { - m_notifyHandler(); - return 0; - } - -private: - std::function m_notifyHandler; -}; diff --git a/DDrawCompat/RealPrimarySurface.h b/DDrawCompat/RealPrimarySurface.h deleted file mode 100644 index 230ac6a..0000000 --- a/DDrawCompat/RealPrimarySurface.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#define CINTERFACE - -#include - -#include "CompatWeakPtr.h" -#include "CompatRef.h" - -class RealPrimarySurface -{ -public: - template - static HRESULT create(CompatRef dd); - - static void disableUpdates(); - static void enableUpdates(); - static HRESULT flip(DWORD flags); - static CompatWeakPtr getSurface(); - static void invalidate(const RECT* rect); - static bool isFullScreen(); - static bool isLost(); - static void release(); - static void removeUpdateThread(); - static HRESULT restore(); - static void setClipper(CompatWeakPtr clipper); - static void setPalette(); - static void update(); - static void updatePalette(DWORD startingEntry, DWORD count); -};