1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Moved DirectDraw parts to DDraw namespace and subdirectory

This commit is contained in:
narzoul 2016-08-27 22:39:28 +02:00
parent b65f98f0e3
commit 55f840cb50
51 changed files with 1963 additions and 1903 deletions

View File

@ -1,17 +0,0 @@
#pragma once
#define CINTERFACE
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Unknwnbase.h>
#include "CompatWeakPtr.h"
namespace CompatActivateAppHandler
{
void installHooks();
bool isActive();
void setFullScreenCooperativeLevel(CompatWeakPtr<IUnknown> dd, HWND hwnd, DWORD flags);
void uninstallHooks();
}

View File

@ -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<IDirectDrawSurface> g_fullScreenTagSurface;
void onReleaseFullScreenTagSurface();
IReleaseNotifier g_fullScreenTagSurfaceReleaseNotifier(&onReleaseFullScreenTagSurface);
CompatPtr<IDirectDrawSurface> createFullScreenTagSurface(CompatRef<IDirectDraw> 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<IDirectDrawSurface> tagSurface;
dd->CreateSurface(&dd, &desc, &tagSurface.getRef(), nullptr);
if (tagSurface)
{
CompatPtr<IDirectDrawSurface7> 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<DirectDrawInterface*>(dd)->ddObject == g_fullScreenDirectDraw->ddObject;
}
void onReleaseFullScreenTagSurface()
{
CompatActivateAppHandler::setFullScreenCooperativeLevel(nullptr, nullptr, 0);
g_fullScreenDirectDraw = nullptr;
g_fullScreenTagSurface = nullptr;
}
void setFullScreenDirectDraw(CompatRef<IDirectDraw> 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<DirectDrawInterface&>(dd.get());
fullScreenDirectDraw.vtable = ddIntf.vtable;
fullScreenDirectDraw.ddObject = ddIntf.ddObject;
g_fullScreenDirectDraw = &fullScreenDirectDraw;
}
}
template <typename TDirectDraw>
void CompatDirectDraw<TDirectDraw>::setCompatVtable(Vtable<TDirectDraw>& vtable)
{
vtable.CreateSurface = &CreateSurface;
vtable.GetDisplayMode = &GetDisplayMode;
vtable.RestoreDisplayMode = &RestoreDisplayMode;
vtable.SetCooperativeLevel = &SetCooperativeLevel;
vtable.SetDisplayMode = &SetDisplayMode;
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE CompatDirectDraw<TDirectDraw>::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<TSurface>::createCompatPrimarySurface<TDirectDraw>(
*This, *lpDDSurfaceDesc, *lplpDDSurface);
}
else
{
if (lpDDSurfaceDesc &&
(lpDDSurfaceDesc->dwFlags & DDSD_WIDTH) &&
(lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT) &&
!(lpDDSurfaceDesc->ddsCaps.dwCaps & (DDSCAPS_ALPHA | DDSCAPS_ZBUFFER)))
{
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(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<TSurface>::fixSurfacePtrs(**lplpDDSurface);
}
return result;
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE CompatDirectDraw<TDirectDraw>::GetDisplayMode(
TDirectDraw* This, TSurfaceDesc* lpDDSurfaceDesc)
{
const DWORD size = lpDDSurfaceDesc ? lpDDSurfaceDesc->dwSize : 0;
if (sizeof(DDSURFACEDESC) != size && sizeof(DDSURFACEDESC2) != size)
{
return DDERR_INVALIDPARAMS;
}
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(This));
const DDSURFACEDESC2 dm = CompatDisplayMode::getDisplayMode(*dd);
CopyMemory(lpDDSurfaceDesc, &dm, size);
lpDDSurfaceDesc->dwSize = size;
return DD_OK;
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE CompatDirectDraw<TDirectDraw>::RestoreDisplayMode(TDirectDraw* This)
{
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(This));
return CompatDisplayMode::restoreDisplayMode(*dd);
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE CompatDirectDraw<TDirectDraw>::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<IDirectDraw> dd(Compat::queryInterface<IDirectDraw>(This));
setFullScreenDirectDraw(*dd);
CompatActivateAppHandler::setFullScreenCooperativeLevel(
reinterpret_cast<IUnknown*>(g_fullScreenDirectDraw), hWnd, dwFlags);
}
else if (isFullScreenDirectDraw(This) && g_fullScreenTagSurface)
{
g_fullScreenTagSurface.release();
}
}
return result;
}
template <typename TDirectDraw>
template <typename... Params>
HRESULT STDMETHODCALLTYPE CompatDirectDraw<TDirectDraw>::SetDisplayMode(
TDirectDraw* This,
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBPP,
Params... params)
{
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(This));
return CompatDisplayMode::setDisplayMode(*dd, dwWidth, dwHeight, dwBPP, params...);
}
template CompatDirectDraw<IDirectDraw>;
template CompatDirectDraw<IDirectDraw2>;
template CompatDirectDraw<IDirectDraw4>;
template CompatDirectDraw<IDirectDraw7>;

View File

@ -1,33 +0,0 @@
#pragma once
#include "CompatVtable.h"
#include "DDrawTypes.h"
#include "DirectDrawVtblVisitor.h"
template <typename TDirectDraw>
class CompatDirectDraw : public CompatVtable<CompatDirectDraw<TDirectDraw>, TDirectDraw>
{
public:
typedef typename Types<TDirectDraw>::TCreatedSurface TSurface;
typedef typename Types<TDirectDraw>::TSurfaceDesc TSurfaceDesc;
static void setCompatVtable(Vtable<TDirectDraw>& 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 <typename... Params>
static HRESULT STDMETHODCALLTYPE SetDisplayMode(
TDirectDraw* This,
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBPP,
Params... params);
};

View File

@ -1,61 +0,0 @@
#include <cstring>
#include <deque>
#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<long long> 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());
}

View File

@ -1,19 +0,0 @@
#pragma once
#include "CompatVtable.h"
#include "DirectDrawPaletteVtblVisitor.h"
class CompatDirectDrawPalette : public CompatVtable<CompatDirectDrawPalette, IDirectDrawPalette>
{
public:
static void setCompatVtable(IDirectDrawPaletteVtbl& vtable);
static HRESULT STDMETHODCALLTYPE SetEntries(
IDirectDrawPalette* This,
DWORD dwFlags,
DWORD dwStartingEntry,
DWORD dwCount,
LPPALETTEENTRY lpEntries);
static void waitForNextUpdate();
};

View File

@ -1,554 +0,0 @@
#include <set>
#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<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
RECT srcRect, DWORD mirrorFx);
bool g_lockingPrimary = false;
void fixSurfacePtr(CompatRef<IDirectDrawSurface7> 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<std::set<IDirectDrawSurface7*>*>(lpContext);
CompatPtr<IDirectDrawSurface7> 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<IDirectDrawSurface7> surface)
{
DDSURFACEDESC2 desc = {};
desc.dwSize = sizeof(desc);
surface->GetSurfaceDesc(&surface, &desc);
fixSurfacePtr(surface, desc);
std::set<IDirectDrawSurface7*> visitedSurfaces{ &surface };
surface->EnumAttachedSurfaces(&surface, &visitedSurfaces, &fixSurfacePtrEnumCallback);
}
CompatWeakPtr<IDirectDrawSurface7> getMirroredSurface(
CompatRef<IDirectDrawSurface7> 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<LONG>(desc.dwWidth), static_cast<LONG>(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<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> 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 <typename TSurface>
void CompatDirectDrawSurface<TSurface>::setCompatVtable(Vtable<TSurface>& 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 <typename TSurface>
template <typename TDirectDraw>
HRESULT CompatDirectDrawSurface<TSurface>::createCompatPrimarySurface(
CompatRef<TDirectDraw> dd,
TSurfaceDesc compatDesc,
TSurface*& compatSurface)
{
HRESULT result = RealPrimarySurface::create(dd);
if (FAILED(result))
{
return result;
}
CompatPtr<IDirectDraw7> dd7(Compat::queryInterface<IDirectDraw7>(&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<IDirectDrawSurface7> primary(Compat::queryInterface<IDirectDrawSurface7>(compatSurface));
CompatPrimarySurface::setPrimary(*primary);
return DD_OK;
}
template <typename TSurface>
void CompatDirectDrawSurface<TSurface>::fixSurfacePtrs(CompatRef<TSurface> surface)
{
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(&surface));
::fixSurfacePtrs(*surface7);
}
template <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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<TSurface> mirroredSrcSurface;
if (lpDDSrcSurface && (dwFlags & DDBLT_DDFX) && lpDDBltFx &&
(lpDDBltFx->dwDDFX & (DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN)))
{
CompatPtr<IDirectDrawSurface7> srcSurface(
Compat::queryInterface<IDirectDrawSurface7>(lpDDSrcSurface));
mirroredSrcSurface.reset(Compat::queryInterface<TSurface>(
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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::GetCaps(
TSurface* This,
TDdsCaps* lpDDSCaps)
{
HRESULT result = s_origVtable.GetCaps(This, lpDDSCaps);
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
{
restorePrimaryCaps(*lpDDSCaps);
}
return result;
}
template <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::SetClipper(
TSurface* This,
LPDIRECTDRAWCLIPPER lpDDClipper)
{
HRESULT result = s_origVtable.SetClipper(This, lpDDClipper);
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
{
RealPrimarySurface::setClipper(lpDDClipper);
}
return result;
}
template <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE CompatDirectDrawSurface<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
{
HRESULT result = s_origVtable.Unlock(This, lpRect);
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
{
RealPrimarySurface::update();
}
return result;
}
template <typename TSurface>
void CompatDirectDrawSurface<TSurface>::restorePrimaryCaps(TDdsCaps& caps)
{
caps.dwCaps &= ~(DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
caps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
}
template CompatDirectDrawSurface<IDirectDrawSurface>;
template CompatDirectDrawSurface<IDirectDrawSurface2>;
template CompatDirectDrawSurface<IDirectDrawSurface3>;
template CompatDirectDrawSurface<IDirectDrawSurface4>;
template CompatDirectDrawSurface<IDirectDrawSurface7>;
template HRESULT CompatDirectDrawSurface<IDirectDrawSurface>::createCompatPrimarySurface(
CompatRef<IDirectDraw> dd,
TSurfaceDesc compatDesc,
IDirectDrawSurface*& compatSurface);
template HRESULT CompatDirectDrawSurface<IDirectDrawSurface>::createCompatPrimarySurface(
CompatRef<IDirectDraw2> dd,
TSurfaceDesc compatDesc,
IDirectDrawSurface*& compatSurface);
template HRESULT CompatDirectDrawSurface<IDirectDrawSurface4>::createCompatPrimarySurface(
CompatRef<IDirectDraw4> dd,
TSurfaceDesc compatDesc,
IDirectDrawSurface4*& compatSurface);
template HRESULT CompatDirectDrawSurface<IDirectDrawSurface7>::createCompatPrimarySurface(
CompatRef<IDirectDraw7> dd,
TSurfaceDesc compatDesc,
IDirectDrawSurface7*& compatSurface);

View File

@ -1,67 +0,0 @@
#pragma once
#include "CompatRef.h"
#include "CompatVtable.h"
#include "DDrawTypes.h"
#include "DirectDrawSurfaceVtblVisitor.h"
template <typename TSurface>
class CompatDirectDrawSurface : public CompatVtable<CompatDirectDrawSurface<TSurface>, TSurface>
{
public:
typedef typename Types<TSurface>::TSurfaceDesc TSurfaceDesc;
typedef typename Types<TSurface>::TDdsCaps TDdsCaps;
typedef typename Types<TSurface>::TUnlockParam TUnlockParam;
static void setCompatVtable(Vtable<TSurface>& vtable);
template <typename TDirectDraw>
static HRESULT createCompatPrimarySurface(
CompatRef<TDirectDraw> dd,
TSurfaceDesc compatDesc,
TSurface*& compatSurface);
static void fixSurfacePtrs(CompatRef<TSurface> 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);
};

View File

@ -1,22 +0,0 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#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<IDirectDraw7> dd);
HRESULT restoreDisplayMode(CompatRef<IDirectDraw7> dd);
HRESULT setDisplayMode(CompatRef<IDirectDraw7> dd,
DWORD width, DWORD height, DWORD bpp, DWORD refreshRate = 0, DWORD flags = 0);
};

View File

@ -1,5 +1,9 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
namespace CompatFontSmoothing
{
struct SystemSettings

View File

@ -1,161 +0,0 @@
#include <algorithm>
#include <cstring>
#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<IDirectDrawSurface7> 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<LONG>(dm.dwHeight);
bmi.header.biPlanes = 1;
bmi.header.biBitCount = static_cast<WORD>(dm.ddpfPixelFormat.dwRGBBitCount);
bmi.header.biCompression = BI_RGB;
return CreateDIBSection(nullptr, reinterpret_cast<BITMAPINFO*>(&bmi),
DIB_RGB_COLORS, &bits, nullptr, 0);
}
CompatPtr<IDirectDrawSurface7> 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<IDirectDrawSurface7> 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<IDirectDrawSurface7> 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<IDirectDrawSurface7> 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<IDirectDrawClipper> 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);
}
}
};

View File

@ -1,17 +0,0 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#include "CompatWeakPtr.h"
namespace CompatPaletteConverter
{
bool create();
HDC getDc();
CompatWeakPtr<IDirectDrawSurface7> getSurface();
void release();
void setClipper(CompatWeakPtr<IDirectDrawClipper> clipper);
void updatePalette(DWORD startingEntry, DWORD count);
}

View File

@ -1,81 +0,0 @@
#include <algorithm>
#include <vector>
#include "CompatDirectDrawSurface.h"
#include "CompatPrimarySurface.h"
#include "CompatPtr.h"
#include "IReleaseNotifier.h"
#include "RealPrimarySurface.h"
namespace
{
void onRelease();
DDSURFACEDESC2 g_primarySurfaceDesc = {};
CompatWeakPtr<IDirectDrawSurface> g_primarySurface = nullptr;
std::vector<void*> 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<IDirectDrawSurface7> getPrimary()
{
if (!g_primarySurface)
{
return nullptr;
}
return CompatPtr<IDirectDrawSurface7>(
Compat::queryInterface<IDirectDrawSurface7>(g_primarySurface.get()));
}
bool isPrimary(void* surface)
{
return g_primarySurfacePtrs.end() !=
std::find(g_primarySurfacePtrs.begin(), g_primarySurfacePtrs.end(), surface);
}
void setPrimary(CompatRef<IDirectDrawSurface7> surface)
{
CompatPtr<IDirectDrawSurface> surfacePtr(Compat::queryInterface<IDirectDrawSurface>(&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<IDirectDrawSurface4>(surfacePtr));
g_primarySurfacePtrs.push_back(CompatPtr<IDirectDrawSurface3>(surfacePtr));
g_primarySurfacePtrs.push_back(CompatPtr<IDirectDrawSurface2>(surfacePtr));
g_primarySurfacePtrs.push_back(surfacePtr);
IReleaseNotifier* releaseNotifierPtr = &g_releaseNotifier;
surface->SetPrivateData(&surface, IID_IReleaseNotifier,
releaseNotifierPtr, sizeof(releaseNotifierPtr), DDSPD_IUNKNOWNPOINTER);
}
CompatWeakPtr<IDirectDrawPalette> g_palette;
PALETTEENTRY g_paletteEntries[256] = {};
}

View File

@ -1,21 +0,0 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#include "CompatPtr.h"
#include "CompatRef.h"
class IReleaseNotifier;
namespace CompatPrimarySurface
{
const DDSURFACEDESC2& getDesc();
CompatPtr<IDirectDrawSurface7> getPrimary();
bool isPrimary(void* surface);
void setPrimary(CompatRef<IDirectDrawSurface7> surface);
extern CompatWeakPtr<IDirectDrawPalette> g_palette;
extern PALETTEENTRY g_paletteEntries[256];
}

View File

@ -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<IDirectDrawSurface7>::fixSurfacePtrs(*primary);
DDraw::DirectDrawSurface<IDirectDrawSurface7>::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<IUnknown> dd, HWND hwnd, DWORD flags)
{
g_fullScreenDirectDraw = dd;
g_fullScreenCooperativeWindow = hwnd;
g_fullScreenCooperativeFlags = flags;
}
void setFullScreenCooperativeLevel(CompatWeakPtr<IUnknown> dd, HWND hwnd, DWORD flags)
{
g_fullScreenDirectDraw = dd;
g_fullScreenCooperativeWindow = hwnd;
g_fullScreenCooperativeFlags = flags;
}
void uninstallHooks()
{
UnhookWindowsHookEx(g_callWndProcHook);
void uninstallHooks()
{
UnhookWindowsHookEx(g_callWndProcHook);
}
}
}

View File

@ -0,0 +1,20 @@
#pragma once
#define CINTERFACE
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Unknwnbase.h>
#include "CompatWeakPtr.h"
namespace DDraw
{
namespace ActivateAppHandler
{
void installHooks();
bool isActive();
void setFullScreenCooperativeLevel(CompatWeakPtr<IUnknown> dd, HWND hwnd, DWORD flags);
void uninstallHooks();
}
}

View File

@ -0,0 +1,85 @@
#include <algorithm>
#include <vector>
#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<IDirectDrawSurface> g_primarySurface = nullptr;
std::vector<void*> 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<IDirectDrawSurface7> getPrimary()
{
if (!g_primarySurface)
{
return nullptr;
}
return CompatPtr<IDirectDrawSurface7>(
Compat::queryInterface<IDirectDrawSurface7>(g_primarySurface.get()));
}
bool isPrimary(void* surface)
{
return g_primarySurfacePtrs.end() !=
std::find(g_primarySurfacePtrs.begin(), g_primarySurfacePtrs.end(), surface);
}
void setPrimary(CompatRef<IDirectDrawSurface7> surface)
{
CompatPtr<IDirectDrawSurface> surfacePtr(Compat::queryInterface<IDirectDrawSurface>(&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<IDirectDrawSurface4>(surfacePtr));
g_primarySurfacePtrs.push_back(CompatPtr<IDirectDrawSurface3>(surfacePtr));
g_primarySurfacePtrs.push_back(CompatPtr<IDirectDrawSurface2>(surfacePtr));
g_primarySurfacePtrs.push_back(surfacePtr);
IReleaseNotifier* releaseNotifierPtr = &g_releaseNotifier;
surface->SetPrivateData(&surface, IID_IReleaseNotifier,
releaseNotifierPtr, sizeof(releaseNotifierPtr), DDSPD_IUNKNOWNPOINTER);
}
CompatWeakPtr<IDirectDrawPalette> g_palette;
PALETTEENTRY g_paletteEntries[256] = {};
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#include "CompatPtr.h"
#include "CompatRef.h"
namespace DDraw
{
namespace CompatPrimarySurface
{
const DDSURFACEDESC2& getDesc();
CompatPtr<IDirectDrawSurface7> getPrimary();
bool isPrimary(void* surface);
void setPrimary(CompatRef<IDirectDrawSurface7> surface);
extern CompatWeakPtr<IDirectDrawPalette> g_palette;
extern PALETTEENTRY g_paletteEntries[256];
}
}

View File

@ -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<IDirectDrawSurface> g_fullScreenTagSurface;
void onReleaseFullScreenTagSurface();
DDraw::IReleaseNotifier g_fullScreenTagSurfaceReleaseNotifier(&onReleaseFullScreenTagSurface);
CompatPtr<IDirectDrawSurface> createFullScreenTagSurface(CompatRef<IDirectDraw> 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<IDirectDrawSurface> tagSurface;
dd->CreateSurface(&dd, &desc, &tagSurface.getRef(), nullptr);
if (tagSurface)
{
CompatPtr<IDirectDrawSurface7> 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<DirectDrawInterface*>(dd)->ddObject == g_fullScreenDirectDraw->ddObject;
}
void onReleaseFullScreenTagSurface()
{
DDraw::ActivateAppHandler::setFullScreenCooperativeLevel(nullptr, nullptr, 0);
g_fullScreenDirectDraw = nullptr;
g_fullScreenTagSurface = nullptr;
}
void setFullScreenDirectDraw(CompatRef<IDirectDraw> 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<DirectDrawInterface&>(dd.get());
fullScreenDirectDraw.vtable = ddIntf.vtable;
fullScreenDirectDraw.ddObject = ddIntf.ddObject;
g_fullScreenDirectDraw = &fullScreenDirectDraw;
}
}
namespace DDraw
{
template <typename TDirectDraw>
void DirectDraw<TDirectDraw>::setCompatVtable(Vtable<TDirectDraw>& vtable)
{
vtable.CreateSurface = &CreateSurface;
vtable.GetDisplayMode = &GetDisplayMode;
vtable.RestoreDisplayMode = &RestoreDisplayMode;
vtable.SetCooperativeLevel = &SetCooperativeLevel;
vtable.SetDisplayMode = &SetDisplayMode;
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE DirectDraw<TDirectDraw>::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<TSurface>::createCompatPrimarySurface<TDirectDraw>(
*This, *lpDDSurfaceDesc, *lplpDDSurface);
}
else
{
if (lpDDSurfaceDesc &&
(lpDDSurfaceDesc->dwFlags & DDSD_WIDTH) &&
(lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT) &&
!(lpDDSurfaceDesc->ddsCaps.dwCaps & (DDSCAPS_ALPHA | DDSCAPS_ZBUFFER)))
{
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(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<TSurface>::fixSurfacePtrs(**lplpDDSurface);
}
return result;
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE DirectDraw<TDirectDraw>::GetDisplayMode(
TDirectDraw* This, TSurfaceDesc* lpDDSurfaceDesc)
{
const DWORD size = lpDDSurfaceDesc ? lpDDSurfaceDesc->dwSize : 0;
if (sizeof(DDSURFACEDESC) != size && sizeof(DDSURFACEDESC2) != size)
{
return DDERR_INVALIDPARAMS;
}
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(This));
const DDSURFACEDESC2 dm = DisplayMode::getDisplayMode(*dd);
CopyMemory(lpDDSurfaceDesc, &dm, size);
lpDDSurfaceDesc->dwSize = size;
return DD_OK;
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE DirectDraw<TDirectDraw>::RestoreDisplayMode(TDirectDraw* This)
{
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(This));
return DisplayMode::restoreDisplayMode(*dd);
}
template <typename TDirectDraw>
HRESULT STDMETHODCALLTYPE DirectDraw<TDirectDraw>::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<IDirectDraw> dd(Compat::queryInterface<IDirectDraw>(This));
setFullScreenDirectDraw(*dd);
ActivateAppHandler::setFullScreenCooperativeLevel(
reinterpret_cast<IUnknown*>(g_fullScreenDirectDraw), hWnd, dwFlags);
}
else if (isFullScreenDirectDraw(This) && g_fullScreenTagSurface)
{
g_fullScreenTagSurface.release();
}
}
return result;
}
template <typename TDirectDraw>
template <typename... Params>
HRESULT STDMETHODCALLTYPE DirectDraw<TDirectDraw>::SetDisplayMode(
TDirectDraw* This,
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBPP,
Params... params)
{
CompatPtr<IDirectDraw7> dd(Compat::queryInterface<IDirectDraw7>(This));
return DisplayMode::setDisplayMode(*dd, dwWidth, dwHeight, dwBPP, params...);
}
template DirectDraw<IDirectDraw>;
template DirectDraw<IDirectDraw2>;
template DirectDraw<IDirectDraw4>;
template DirectDraw<IDirectDraw7>;
}

View File

@ -0,0 +1,36 @@
#pragma once
#include "CompatVtable.h"
#include "DDraw/Types.h"
#include "DirectDrawVtblVisitor.h"
namespace DDraw
{
template <typename TDirectDraw>
class DirectDraw: public CompatVtable<DirectDraw<TDirectDraw>, TDirectDraw>
{
public:
typedef typename Types<TDirectDraw>::TCreatedSurface TSurface;
typedef typename Types<TDirectDraw>::TSurfaceDesc TSurfaceDesc;
static void setCompatVtable(Vtable<TDirectDraw>& 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 <typename... Params>
static HRESULT STDMETHODCALLTYPE SetDisplayMode(
TDirectDraw* This,
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBPP,
Params... params);
};
}

View File

@ -0,0 +1,64 @@
#include <cstring>
#include <deque>
#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<long long> 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());
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "CompatVtable.h"
#include "DirectDrawPaletteVtblVisitor.h"
namespace DDraw
{
class DirectDrawPalette : public CompatVtable<DirectDrawPalette, IDirectDrawPalette>
{
public:
static void setCompatVtable(IDirectDrawPaletteVtbl& vtable);
static HRESULT STDMETHODCALLTYPE SetEntries(
IDirectDrawPalette* This,
DWORD dwFlags,
DWORD dwStartingEntry,
DWORD dwCount,
LPPALETTEENTRY lpEntries);
static void waitForNextUpdate();
};
}

View File

@ -0,0 +1,558 @@
#include <set>
#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<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
RECT srcRect, DWORD mirrorFx);
bool g_lockingPrimary = false;
void fixSurfacePtr(CompatRef<IDirectDrawSurface7> 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<std::set<IDirectDrawSurface7*>*>(lpContext);
CompatPtr<IDirectDrawSurface7> 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<IDirectDrawSurface7> surface)
{
DDSURFACEDESC2 desc = {};
desc.dwSize = sizeof(desc);
surface->GetSurfaceDesc(&surface, &desc);
fixSurfacePtr(surface, desc);
std::set<IDirectDrawSurface7*> visitedSurfaces{ &surface };
surface->EnumAttachedSurfaces(&surface, &visitedSurfaces, &fixSurfacePtrEnumCallback);
}
CompatWeakPtr<IDirectDrawSurface7> getMirroredSurface(
CompatRef<IDirectDrawSurface7> 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<LONG>(desc.dwWidth), static_cast<LONG>(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<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> 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 <typename TSurface>
void DirectDrawSurface<TSurface>::setCompatVtable(Vtable<TSurface>& 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 <typename TSurface>
template <typename TDirectDraw>
HRESULT DirectDrawSurface<TSurface>::createCompatPrimarySurface(
CompatRef<TDirectDraw> dd,
TSurfaceDesc compatDesc,
TSurface*& compatSurface)
{
HRESULT result = RealPrimarySurface::create(dd);
if (FAILED(result))
{
return result;
}
CompatPtr<IDirectDraw7> dd7(Compat::queryInterface<IDirectDraw7>(&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<IDirectDrawSurface7> primary(Compat::queryInterface<IDirectDrawSurface7>(compatSurface));
CompatPrimarySurface::setPrimary(*primary);
return DD_OK;
}
template <typename TSurface>
void DirectDrawSurface<TSurface>::fixSurfacePtrs(CompatRef<TSurface> surface)
{
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(&surface));
::fixSurfacePtrs(*surface7);
}
template <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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<TSurface> mirroredSrcSurface;
if (lpDDSrcSurface && (dwFlags & DDBLT_DDFX) && lpDDBltFx &&
(lpDDBltFx->dwDDFX & (DDBLTFX_MIRRORLEFTRIGHT | DDBLTFX_MIRRORUPDOWN)))
{
CompatPtr<IDirectDrawSurface7> srcSurface(
Compat::queryInterface<IDirectDrawSurface7>(lpDDSrcSurface));
mirroredSrcSurface.reset(Compat::queryInterface<TSurface>(
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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::GetCaps(
TSurface* This,
TDdsCaps* lpDDSCaps)
{
HRESULT result = s_origVtable.GetCaps(This, lpDDSCaps);
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
{
restorePrimaryCaps(*lpDDSCaps);
}
return result;
}
template <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::SetClipper(
TSurface* This,
LPDIRECTDRAWCLIPPER lpDDClipper)
{
HRESULT result = s_origVtable.SetClipper(This, lpDDClipper);
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
{
RealPrimarySurface::setClipper(lpDDClipper);
}
return result;
}
template <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::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 <typename TSurface>
HRESULT STDMETHODCALLTYPE DirectDrawSurface<TSurface>::Unlock(TSurface* This, TUnlockParam lpRect)
{
HRESULT result = s_origVtable.Unlock(This, lpRect);
if (SUCCEEDED(result) && CompatPrimarySurface::isPrimary(This))
{
RealPrimarySurface::update();
}
return result;
}
template <typename TSurface>
void DirectDrawSurface<TSurface>::restorePrimaryCaps(TDdsCaps& caps)
{
caps.dwCaps &= ~(DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
caps.dwCaps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE | DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
}
template DirectDrawSurface<IDirectDrawSurface>;
template DirectDrawSurface<IDirectDrawSurface2>;
template DirectDrawSurface<IDirectDrawSurface3>;
template DirectDrawSurface<IDirectDrawSurface4>;
template DirectDrawSurface<IDirectDrawSurface7>;
template HRESULT DirectDrawSurface<IDirectDrawSurface>::createCompatPrimarySurface(
CompatRef<IDirectDraw> dd,
TSurfaceDesc compatDesc,
IDirectDrawSurface*& compatSurface);
template HRESULT DirectDrawSurface<IDirectDrawSurface>::createCompatPrimarySurface(
CompatRef<IDirectDraw2> dd,
TSurfaceDesc compatDesc,
IDirectDrawSurface*& compatSurface);
template HRESULT DirectDrawSurface<IDirectDrawSurface4>::createCompatPrimarySurface(
CompatRef<IDirectDraw4> dd,
TSurfaceDesc compatDesc,
IDirectDrawSurface4*& compatSurface);
template HRESULT DirectDrawSurface<IDirectDrawSurface7>::createCompatPrimarySurface(
CompatRef<IDirectDraw7> dd,
TSurfaceDesc compatDesc,
IDirectDrawSurface7*& compatSurface);
}

View File

@ -0,0 +1,70 @@
#pragma once
#include "CompatRef.h"
#include "CompatVtable.h"
#include "DDraw/Types.h"
#include "DirectDrawSurfaceVtblVisitor.h"
namespace DDraw
{
template <typename TSurface>
class DirectDrawSurface : public CompatVtable<DirectDrawSurface<TSurface>, TSurface>
{
public:
typedef typename Types<TSurface>::TSurfaceDesc TSurfaceDesc;
typedef typename Types<TSurface>::TDdsCaps TDdsCaps;
typedef typename Types<TSurface>::TUnlockParam TUnlockParam;
static void setCompatVtable(Vtable<TSurface>& vtable);
template <typename TDirectDraw>
static HRESULT createCompatPrimarySurface(
CompatRef<TDirectDraw> dd,
TSurfaceDesc compatDesc,
TSurface*& compatSurface);
static void fixSurfacePtrs(CompatRef<TSurface> 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);
};
}

View File

@ -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<IDirectDrawSurface7> 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<IDirectDraw7> 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<IDirectDraw7> dd)
{
const HRESULT result = dd->RestoreDisplayMode(&dd);
if (SUCCEEDED(result))
{
ZeroMemory(&g_emulatedDisplayMode, sizeof(g_emulatedDisplayMode));
releaseCompatibleDc();
}
return result;
}
HRESULT setDisplayMode(CompatRef<IDirectDraw7> 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<IDirectDraw7> 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<IDirectDraw7> 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<IDirectDraw7> 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;
}
}
}

View File

@ -0,0 +1,25 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#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<IDirectDraw7> dd);
HRESULT restoreDisplayMode(CompatRef<IDirectDraw7> dd);
HRESULT setDisplayMode(CompatRef<IDirectDraw7> dd,
DWORD width, DWORD height, DWORD bpp, DWORD refreshRate = 0, DWORD flags = 0);
};
}

View File

@ -2,19 +2,19 @@
#include <d3d.h>
#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<IDirectDraw7> dd)
{
CompatDirectDraw<IDirectDraw7>::s_origVtable = *(&dd)->lpVtbl;
DDraw::DirectDraw<IDirectDraw7>::s_origVtable = *(&dd)->lpVtbl;
CompatPtr<IDirectDraw7> dd7(&dd);
hookVtable<CompatDirectDraw<IDirectDraw>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw2>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw4>>(dd7);
hookVtable<CompatDirectDraw<IDirectDraw7>>(dd7);
hookVtable<DDraw::DirectDraw<IDirectDraw>>(dd7);
hookVtable<DDraw::DirectDraw<IDirectDraw2>>(dd7);
hookVtable<DDraw::DirectDraw<IDirectDraw4>>(dd7);
hookVtable<DDraw::DirectDraw<IDirectDraw7>>(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<IDirectDrawSurface7>::s_origVtable = *surface.get()->lpVtbl;
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface2>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface3>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface4>>(surface);
hookVtable<CompatDirectDrawSurface<IDirectDrawSurface7>>(surface);
DDraw::DirectDrawSurface<IDirectDrawSurface7>::s_origVtable = *surface.get()->lpVtbl;
hookVtable<DDraw::DirectDrawSurface<IDirectDrawSurface>>(surface);
hookVtable<DDraw::DirectDrawSurface<IDirectDrawSurface2>>(surface);
hookVtable<DDraw::DirectDrawSurface<IDirectDrawSurface3>>(surface);
hookVtable<DDraw::DirectDrawSurface<IDirectDrawSurface4>>(surface);
hookVtable<DDraw::DirectDrawSurface<IDirectDrawSurface7>>(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();
}
}

View File

@ -1,6 +1,6 @@
#pragma once
namespace DDrawHooks
namespace DDraw
{
void installHooks();
void uninstallHooks();

View File

@ -1,4 +1,4 @@
#include "IReleaseNotifier.h"
#include "DDraw/IReleaseNotifier.h"
#include <initguid.h>

View File

@ -0,0 +1,40 @@
#pragma once
#include <functional>
#include <Unknwnbase.h>
// {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<void()>& 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<void()> m_notifyHandler;
};
}

View File

@ -0,0 +1,164 @@
#include <algorithm>
#include <cstring>
#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<IDirectDrawSurface7> 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<LONG>(dm.dwHeight);
bmi.header.biPlanes = 1;
bmi.header.biBitCount = static_cast<WORD>(dm.ddpfPixelFormat.dwRGBBitCount);
bmi.header.biCompression = BI_RGB;
return CreateDIBSection(nullptr, reinterpret_cast<BITMAPINFO*>(&bmi),
DIB_RGB_COLORS, &bits, nullptr, 0);
}
CompatPtr<IDirectDrawSurface7> 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<IDirectDrawSurface7> 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<IDirectDrawSurface7> 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<IDirectDrawSurface7> 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<IDirectDrawClipper> 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);
}
}
};
}

View File

@ -0,0 +1,20 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#include "CompatWeakPtr.h"
namespace DDraw
{
namespace PaletteConverter
{
bool create();
HDC getDc();
CompatWeakPtr<IDirectDrawSurface7> getSurface();
void release();
void setClipper(CompatWeakPtr<IDirectDrawClipper> clipper);
void updatePalette(DWORD startingEntry, DWORD count);
}
}

View File

@ -1,17 +1,17 @@
#include <atomic>
#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<IDirectDrawSurface7> g_backBuffer;
CompatWeakPtr<IDirectDrawClipper> 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<IDirectDrawSurface7> 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 <typename DirectDraw>
HRESULT RealPrimarySurface::create(CompatRef<DirectDraw> dd)
namespace DDraw
{
typename Types<DirectDraw>::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<typename Types<DirectDraw>::TCreatedSurface> surface;
HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
bool isFlippable = true;
if (DDERR_NOEXCLUSIVEMODE == result)
template <typename DirectDraw>
HRESULT RealPrimarySurface::create(CompatRef<DirectDraw> 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<DirectDraw>::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<typename Types<DirectDraw>::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<IDirectDraw>);
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw2>);
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw4>);
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw7>);
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<IDirectDraw>);
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw2>);
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw4>);
template HRESULT RealPrimarySurface::create(CompatRef<IDirectDraw7>);
void RealPrimarySurface::disableUpdates()
{
++g_disableUpdateCount;
ResetEvent(g_updateEvent);
}
void RealPrimarySurface::enableUpdates()
{
if (0 == --g_disableUpdateCount)
CompatWeakPtr<IDirectDrawSurface7> 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<IDirectDrawSurface7> 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<IDirectDrawClipper> 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<IDirectDrawClipper> 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();
}
}

View File

@ -0,0 +1,33 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#include "CompatWeakPtr.h"
#include "CompatRef.h"
namespace DDraw
{
class RealPrimarySurface
{
public:
template <typename DirectDraw>
static HRESULT create(CompatRef<DirectDraw> dd);
static void disableUpdates();
static void enableUpdates();
static HRESULT flip(DWORD flags);
static CompatWeakPtr<IDirectDrawSurface7> 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<IDirectDrawClipper> clipper);
static void setPalette();
static void update();
static void updatePalette(DWORD startingEntry, DWORD count);
};
}

View File

@ -2,13 +2,13 @@
#include <vector>
#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<Surface> g_sysMemSurfaces;
static std::vector<Surface> 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<IDirectDraw7> getDirectDraw()
{
static auto dd = new CompatPtr<IDirectDraw7>(createDirectDraw());
return *dd;
CompatWeakPtr<IDirectDraw7> getDirectDraw()
{
static auto dd = new CompatPtr<IDirectDraw7>(createDirectDraw());
return *dd;
}
}
}

View File

@ -0,0 +1,28 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#include "CompatWeakPtr.h"
namespace DDraw
{
namespace Repository
{
struct Surface
{
DDSURFACEDESC2 desc;
CompatWeakPtr<IDirectDrawSurface7> surface;
};
class ScopedSurface : public Surface
{
public:
ScopedSurface(const DDSURFACEDESC2& desc);
~ScopedSurface();
};
CompatWeakPtr<IDirectDraw7> getDirectDraw();
}
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "DDrawProcs.h"
namespace DDraw
{
class ScopedThreadLock
{
public:
ScopedThreadLock()
{
Compat::origProcs.AcquireDDThreadLock();
}
~ScopedThreadLock()
{
Compat::origProcs.ReleaseDDThreadLock();
}
};
}

72
DDrawCompat/DDraw/Types.h Normal file
View File

@ -0,0 +1,72 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
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 <typename Interface>
struct Types;
template <> struct Types<IDirectDraw> : Types1 {};
template <> struct Types<IDirectDraw2> : Types2 {};
template <> struct Types<IDirectDraw4> : Types4 {};
template <> struct Types<IDirectDraw7> : Types7 {};
template <> struct Types<IDirectDrawSurface> : Types1 {};
template <> struct Types<IDirectDrawSurface2> : Types2 {};
template <> struct Types<IDirectDrawSurface3> : Types3 {};
template <> struct Types<IDirectDrawSurface4> : Types4 {};
template <> struct Types<IDirectDrawSurface7> : Types7 {};
}

View File

@ -147,7 +147,6 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="CompatActivateAppHandler.h" />
<ClInclude Include="CompatD3dDdiAdapterCallbacks.h" />
<ClInclude Include="CompatD3dDdiAdapterFuncs.h" />
<ClInclude Include="CompatD3dDdiDeviceCallbacks.h" />
@ -155,15 +154,13 @@
<ClInclude Include="CompatDepthBuffer.h" />
<ClInclude Include="CompatDirect3d.h" />
<ClInclude Include="CompatDirect3dDevice.h" />
<ClInclude Include="CompatDirectDrawPalette.h" />
<ClInclude Include="CompatDisplayMode.h" />
<ClInclude Include="CompatFontSmoothing.h" />
<ClInclude Include="CompatHooks.h" />
<ClInclude Include="CompatPaletteConverter.h" />
<ClInclude Include="CompatPtr.h" />
<ClInclude Include="CompatQueryInterface.h" />
<ClInclude Include="CompatRef.h" />
<ClInclude Include="CompatRegistry.h" />
<ClInclude Include="CompatVtable.h" />
<ClInclude Include="CompatWeakPtr.h" />
<ClInclude Include="Config.h" />
<ClInclude Include="D3dDdiAdapterCallbacksVisitor.h" />
@ -171,16 +168,21 @@
<ClInclude Include="D3dDdiDeviceCallbacksVisitor.h" />
<ClInclude Include="D3dDdiDeviceFuncsVisitor.h" />
<ClInclude Include="D3dDdiHooks.h" />
<ClInclude Include="DDrawHooks.h" />
<ClInclude Include="DDrawProcs.h" />
<ClInclude Include="CompatDirectDraw.h" />
<ClInclude Include="CompatPrimarySurface.h" />
<ClInclude Include="DDrawRepository.h" />
<ClInclude Include="DDrawScopedThreadLock.h" />
<ClInclude Include="DDrawTypes.h" />
<ClInclude Include="CompatDirectDrawSurface.h" />
<ClInclude Include="DDrawVtableVisitor.h" />
<ClInclude Include="CompatVtable.h" />
<ClInclude Include="DDraw\ActivateAppHandler.h" />
<ClInclude Include="DDraw\DirectDraw.h" />
<ClInclude Include="DDraw\DirectDrawPalette.h" />
<ClInclude Include="DDraw\DirectDrawSurface.h" />
<ClInclude Include="DDraw\DisplayMode.h" />
<ClInclude Include="DDraw\PaletteConverter.h" />
<ClInclude Include="DDraw\CompatPrimarySurface.h" />
<ClInclude Include="DDraw\Hooks.h" />
<ClInclude Include="DDraw\Repository.h" />
<ClInclude Include="DDraw\ScopedThreadLock.h" />
<ClInclude Include="DDraw\Types.h" />
<ClInclude Include="DDraw\IReleaseNotifier.h" />
<ClInclude Include="DDraw\RealPrimarySurface.h" />
<ClInclude Include="Direct3dDeviceVtblVisitor.h" />
<ClInclude Include="Direct3dTypes.h" />
<ClInclude Include="Direct3dVtblVisitor.h" />
@ -199,13 +201,10 @@
<ClInclude Include="Gdi\TitleBar.h" />
<ClInclude Include="Gdi\WinProc.h" />
<ClInclude Include="Hook.h" />
<ClInclude Include="IReleaseNotifier.h" />
<ClInclude Include="RealPrimarySurface.h" />
<ClInclude Include="ScopedCriticalSection.h" />
<ClInclude Include="Time.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CompatActivateAppHandler.cpp" />
<ClCompile Include="CompatD3dDdiAdapterCallbacks.cpp" />
<ClCompile Include="CompatD3dDdiAdapterFuncs.cpp" />
<ClCompile Include="CompatD3dDdiDeviceCallbacks.cpp" />
@ -213,19 +212,23 @@
<ClCompile Include="CompatDepthBuffer.cpp" />
<ClCompile Include="CompatDirect3d.cpp" />
<ClCompile Include="CompatDirect3dDevice.cpp" />
<ClCompile Include="CompatDirectDraw.cpp" />
<ClCompile Include="CompatDirectDrawPalette.cpp" />
<ClCompile Include="CompatDirectDrawSurface.cpp" />
<ClCompile Include="CompatDisplayMode.cpp" />
<ClCompile Include="CompatFontSmoothing.cpp" />
<ClCompile Include="CompatHooks.cpp" />
<ClCompile Include="CompatPaletteConverter.cpp" />
<ClCompile Include="CompatRegistry.cpp" />
<ClCompile Include="D3dDdiHooks.cpp" />
<ClCompile Include="DDrawHooks.cpp" />
<ClCompile Include="DDrawLog.cpp" />
<ClCompile Include="DDraw\ActivateAppHandler.cpp" />
<ClCompile Include="DDraw\DirectDraw.cpp" />
<ClCompile Include="DDraw\DirectDrawPalette.cpp" />
<ClCompile Include="DDraw\DirectDrawSurface.cpp" />
<ClCompile Include="DDraw\DisplayMode.cpp" />
<ClCompile Include="DDraw\PaletteConverter.cpp" />
<ClCompile Include="DDraw\CompatPrimarySurface.cpp" />
<ClCompile Include="DDraw\Hooks.cpp" />
<ClCompile Include="DDraw\Repository.cpp" />
<ClCompile Include="DDraw\IReleaseNotifier.cpp" />
<ClCompile Include="DDraw\RealPrimarySurface.cpp" />
<ClCompile Include="DllMain.cpp" />
<ClCompile Include="CompatPrimarySurface.cpp" />
<ClCompile Include="DDrawProcs.cpp" />
<ClCompile Include="Gdi\Gdi.cpp" />
<ClCompile Include="Gdi\Caret.cpp" />
@ -238,9 +241,6 @@
<ClCompile Include="Gdi\TitleBar.cpp" />
<ClCompile Include="Gdi\WinProc.cpp" />
<ClCompile Include="Hook.cpp" />
<ClCompile Include="IReleaseNotifier.cpp" />
<ClCompile Include="RealPrimarySurface.cpp" />
<ClCompile Include="DDrawRepository.cpp" />
<ClCompile Include="Time.cpp" />
<ClCompile Include="UnmodifiedDDrawProcs.cpp" />
</ItemGroup>

View File

@ -19,26 +19,20 @@
<Filter Include="Source Files\Gdi">
<UniqueIdentifier>{a8e1437a-7bec-4492-830a-9a0d844aa06b}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\DDraw">
<UniqueIdentifier>{370ccd34-b783-421b-87fc-84ce703e851d}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\DDraw">
<UniqueIdentifier>{bcc85014-8548-43ff-902f-16bcb6a0e96b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="DDrawProcs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatDirectDraw.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DDrawTypes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatDirectDrawSurface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DDrawVtableVisitor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatVtable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DDrawLog.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -51,45 +45,21 @@
<ClInclude Include="DirectDrawPaletteVtblVisitor.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatDirectDrawPalette.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RealPrimarySurface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatPrimarySurface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IReleaseNotifier.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DDrawScopedThreadLock.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Hook.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatRegistry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DDrawRepository.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatPaletteConverter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ScopedCriticalSection.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Time.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatActivateAppHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatPtr.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -102,9 +72,6 @@
<ClInclude Include="CompatRef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatDisplayMode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatFontSmoothing.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -117,9 +84,6 @@
<ClInclude Include="CompatDirect3d.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DDrawHooks.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Direct3dDeviceVtblVisitor.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -189,6 +153,48 @@
<ClInclude Include="Gdi\WinProc.h">
<Filter>Header Files\Gdi</Filter>
</ClInclude>
<ClInclude Include="CompatVtable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DDraw\CompatPrimarySurface.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\IReleaseNotifier.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\RealPrimarySurface.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\ActivateAppHandler.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\DisplayMode.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\PaletteConverter.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\Hooks.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\Repository.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\ScopedThreadLock.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\Types.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\DirectDraw.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\DirectDrawPalette.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
<ClInclude Include="DDraw\DirectDrawSurface.h">
<Filter>Header Files\DDraw</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="DllMain.cpp">
@ -203,45 +209,15 @@
<ClCompile Include="DDrawLog.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RealPrimarySurface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatPrimarySurface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="IReleaseNotifier.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatDirectDraw.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatDirectDrawSurface.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatDirectDrawPalette.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Hook.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatRegistry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DDrawRepository.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatPaletteConverter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Time.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatActivateAppHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatDisplayMode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatFontSmoothing.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -251,9 +227,6 @@
<ClCompile Include="CompatDirect3d.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DDrawHooks.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatDirect3dDevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -305,6 +278,39 @@
<ClCompile Include="Gdi\WinProc.cpp">
<Filter>Source Files\Gdi</Filter>
</ClCompile>
<ClCompile Include="DDraw\CompatPrimarySurface.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\IReleaseNotifier.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\RealPrimarySurface.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\ActivateAppHandler.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\DisplayMode.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\PaletteConverter.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\Hooks.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\Repository.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\DirectDraw.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\DirectDrawPalette.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
<ClCompile Include="DDraw\DirectDrawSurface.cpp">
<Filter>Source Files\DDraw</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="DDrawCompat.def">

View File

@ -1,25 +0,0 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#include "CompatWeakPtr.h"
namespace DDrawRepository
{
struct Surface
{
DDSURFACEDESC2 desc;
CompatWeakPtr<IDirectDrawSurface7> surface;
};
class ScopedSurface : public Surface
{
public:
ScopedSurface(const DDSURFACEDESC2& desc);
~ScopedSurface();
};
CompatWeakPtr<IDirectDraw7> getDirectDraw();
}

View File

@ -1,20 +0,0 @@
#pragma once
#include "DDrawProcs.h"
namespace Compat
{
class DDrawScopedThreadLock
{
public:
DDrawScopedThreadLock()
{
origProcs.AcquireDDThreadLock();
}
~DDrawScopedThreadLock()
{
origProcs.ReleaseDDThreadLock();
}
};
}

View File

@ -1,79 +0,0 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
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 <typename Interface>
struct Types;
#define DD_CONCAT(x, y, ...) x##y
#define DD_TYPES(Interface, ...) \
template <> \
struct Types<DD_CONCAT(Interface, __VA_ARGS__)> : 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

View File

@ -5,12 +5,12 @@
#include <Windows.h>
#include <Uxtheme.h>
#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();

View File

@ -1,12 +1,12 @@
#include <cstring>
#include <vector>
#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<IDirectDrawSurface7> 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<IDirectDrawSurface7> 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;
}
}

View File

@ -1,6 +1,6 @@
#include <unordered_map>
#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);

View File

@ -1,7 +1,8 @@
#include <atomic>
#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);
}

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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;
}

View File

@ -1,37 +0,0 @@
#pragma once
#include <functional>
#include <Unknwnbase.h>
// {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<void()>& 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<void()> m_notifyHandler;
};

View File

@ -1,30 +0,0 @@
#pragma once
#define CINTERFACE
#include <ddraw.h>
#include "CompatWeakPtr.h"
#include "CompatRef.h"
class RealPrimarySurface
{
public:
template <typename DirectDraw>
static HRESULT create(CompatRef<DirectDraw> dd);
static void disableUpdates();
static void enableUpdates();
static HRESULT flip(DWORD flags);
static CompatWeakPtr<IDirectDrawSurface7> 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<IDirectDrawClipper> clipper);
static void setPalette();
static void update();
static void updatePalette(DWORD startingEntry, DWORD count);
};