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

Reverted forcing surfaces to system memory

This commit is contained in:
narzoul 2019-01-12 12:32:57 +01:00
parent 5b171691f0
commit 26f8742dc2
16 changed files with 56 additions and 537 deletions

View File

@ -2,7 +2,6 @@
#include "D3dDdi/KernelModeThunks.h"
#include "DDraw/ActivateAppHandler.h"
#include "DDraw/DirectDraw.h"
#include "DDraw/Repository.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "Win32/DisplayMode.h"

View File

@ -1,6 +1,3 @@
#include <d3d.h>
#include "Common/CompatPtr.h"
#include "Common/CompatRef.h"
#include "Common/Log.h"
#include "DDraw/ActivateAppHandler.h"
@ -11,8 +8,6 @@
#include "DDraw/DirectDrawSurface.h"
#include "DDraw/Hooks.h"
#include "DDraw/RealPrimarySurface.h"
#include "DDraw/Repository.h"
#include "Dll/Procs.h"
#include "Win32/Registry.h"
namespace
@ -20,15 +15,12 @@ namespace
template <typename Interface>
void hookVtable(const CompatPtr<Interface>& intf);
void hookDirectDraw(CompatRef<IDirectDraw7> dd)
void hookDirectDraw(CompatPtr<IDirectDraw7> dd)
{
DDraw::DirectDraw<IDirectDraw7>::s_origVtable = *(&dd)->lpVtbl;
CompatPtr<IDirectDraw7> dd7(&dd);
hookVtable<IDirectDraw>(dd7);
hookVtable<IDirectDraw2>(dd7);
hookVtable<IDirectDraw4>(dd7);
hookVtable<IDirectDraw7>(dd7);
dd7.detach();
hookVtable<IDirectDraw>(dd);
hookVtable<IDirectDraw2>(dd);
hookVtable<IDirectDraw4>(dd);
hookVtable<IDirectDraw7>(dd);
}
void hookDirectDrawClipper(CompatRef<IDirectDraw7> dd)
@ -100,7 +92,7 @@ namespace
namespace DDraw
{
void installHooks()
void installHooks(CompatPtr<IDirectDraw7> dd7)
{
RealPrimarySurface::init();
ActivateAppHandler::installHooks();
@ -110,29 +102,7 @@ namespace DDraw
Win32::Registry::unsetValue(
HKEY_LOCAL_MACHINE, "SOFTWARE\\WOW6432Node\\Microsoft\\DirectDraw", "EmulationOnly");
CompatPtr<IDirectDraw> dd;
CALL_ORIG_PROC(DirectDrawCreate, nullptr, &dd.getRef(), nullptr);
if (!dd)
{
Compat::Log() << "ERROR: Failed to create a DirectDraw object for hooking";
return;
}
HRESULT result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL);
if (FAILED(result))
{
Compat::Log() << "ERROR: Failed to set the cooperative level for hooking: " << Compat::hex(result);
return;
}
auto dd7(Repository::getDirectDraw());
if (!dd7)
{
Compat::Log() << "ERROR: Failed to create a DirectDraw7 object for hooking";
return;
}
hookDirectDraw(*dd7);
hookDirectDraw(dd7);
hookDirectDrawClipper(*dd7);
hookDirectDrawPalette(*dd7);
hookDirectDrawSurface(*dd7);

View File

@ -1,7 +1,11 @@
#pragma once
#include <ddraw.h>
#include "Common/CompatPtr.h"
namespace DDraw
{
void installHooks();
void installHooks(CompatPtr<IDirectDraw7> dd7);
void uninstallHooks();
}

View File

@ -318,7 +318,7 @@ namespace
const bool isFlippable = 0 != (desc.ddsCaps.dwCaps & DDSCAPS_FLIP);
if (!isFlippable)
{
CALL_ORIG_PROC(DirectDrawCreateClipper, 0, &g_clipper.getRef(), nullptr);
CALL_ORIG_PROC(DirectDrawCreateClipper)(0, &g_clipper.getRef(), nullptr);
g_frontBuffer->SetClipper(g_frontBuffer, g_clipper);
}

View File

@ -1,233 +0,0 @@
#include <algorithm>
#include <map>
#include <vector>
#include "Common/CompatPtr.h"
#include "Common/Log.h"
#include "DDraw/DirectDraw.h"
#include "DDraw/Repository.h"
#include "Dll/Procs.h"
namespace
{
using DDraw::Repository::Surface;
struct Repository
{
CompatWeakPtr<IDirectDraw7> dd;
std::vector<Surface> surfaces;
};
Repository g_sysMemRepo;
std::map<void*, Repository> g_vidMemRepos;
CompatPtr<IDirectDraw7> createDirectDraw();
Surface createSurface(CompatRef<IDirectDraw7> dd,
DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps);
std::vector<Surface>::iterator findSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf,
std::vector<Surface>& cachedSurfaces);
void destroySmallerSurfaces(DWORD width, DWORD height, const DDPIXELFORMAT& pf,
std::vector<Surface>& cachedSurfaces);
Surface getSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc);
void normalizePixelFormat(DDPIXELFORMAT& pf);
void returnSurface(const Surface& surface);
CompatPtr<IDirectDraw7> createDirectDraw()
{
CompatPtr<IDirectDraw7> dd;
HRESULT result = CALL_ORIG_PROC(DirectDrawCreateEx, nullptr,
reinterpret_cast<void**>(&dd.getRef()), IID_IDirectDraw7, nullptr);
if (FAILED(result))
{
LOG_ONCE("ERROR: Failed to create a DirectDraw object in the repository: " << Compat::hex(result));
return nullptr;
}
result = dd.get()->lpVtbl->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL);
if (FAILED(result))
{
LOG_ONCE("ERROR: Failed to set the cooperative level in the repository: " << Compat::hex(result));
return nullptr;
}
return dd;
}
Surface createSurface(CompatRef<IDirectDraw7> dd,
DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps)
{
Surface surface = {};
surface.desc.dwSize = sizeof(surface.desc);
surface.desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
surface.desc.dwWidth = width;
surface.desc.dwHeight = height;
surface.desc.ddpfPixelFormat = pf;
surface.desc.ddsCaps.dwCaps = caps;
dd->CreateSurface(&dd, &surface.desc, &surface.surface.getRef(), nullptr);
return surface;
}
void destroySmallerSurfaces(DWORD width, DWORD height, const DDPIXELFORMAT& pf,
std::vector<Surface>& cachedSurfaces)
{
auto it = cachedSurfaces.begin();
while (it != cachedSurfaces.end())
{
if (it->desc.dwWidth <= width && it->desc.dwHeight <= height &&
0 == memcmp(&it->desc.ddpfPixelFormat, &pf, sizeof(pf)))
{
it->surface.release();
it = cachedSurfaces.erase(it);
}
else
{
++it;
}
}
}
std::vector<Surface>::iterator findSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf,
std::vector<Surface>& cachedSurfaces)
{
auto it = cachedSurfaces.begin();
while (it != cachedSurfaces.end())
{
if (it->desc.dwWidth >= width && it->desc.dwHeight >= height &&
0 == memcmp(&it->desc.ddpfPixelFormat, &pf, sizeof(pf)))
{
if (FAILED(it->surface->IsLost(it->surface)) &&
FAILED(it->surface->Restore(it->surface)))
{
it->surface.release();
it = cachedSurfaces.erase(it);
continue;
}
return it;
}
++it;
}
return cachedSurfaces.end();
}
Repository& getRepository(CompatRef<IDirectDraw7> dd, DWORD caps)
{
if (caps & DDSCAPS_SYSTEMMEMORY)
{
g_sysMemRepo.dd = DDraw::Repository::getDirectDraw();
return g_sysMemRepo;
}
void* ddObject = DDraw::getDdObject(dd.get());
auto it = g_vidMemRepos.find(ddObject);
if (it == g_vidMemRepos.end())
{
Repository repo = {};
repo.dd = createDirectDraw().detach();
return g_vidMemRepos[ddObject] = repo;
}
return it->second;
}
Surface getSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc)
{
Repository& repo = getRepository(dd, desc.ddsCaps.dwCaps);
if (!repo.dd)
{
return Surface();
}
DDPIXELFORMAT pf = desc.ddpfPixelFormat;
normalizePixelFormat(pf);
auto it = findSurface(desc.dwWidth, desc.dwHeight, pf, repo.surfaces);
if (it != repo.surfaces.end())
{
Surface cachedSurface = *it;
repo.surfaces.erase(it);
return cachedSurface;
}
const DWORD memFlag = (desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
? DDSCAPS_SYSTEMMEMORY : DDSCAPS_VIDEOMEMORY;
Surface newSurface = createSurface(*repo.dd, desc.dwWidth, desc.dwHeight, pf,
DDSCAPS_OFFSCREENPLAIN | memFlag);
if (newSurface.surface)
{
newSurface.ddObject = DDraw::getDdObject(dd.get());
destroySmallerSurfaces(desc.dwWidth, desc.dwHeight, pf, repo.surfaces);
}
return newSurface;
}
void normalizePixelFormat(DDPIXELFORMAT& pf)
{
if (!(pf.dwFlags & DDPF_FOURCC))
{
pf.dwFourCC = 0;
}
if (!(pf.dwFlags & (DDPF_ALPHAPIXELS | DDPF_ZPIXELS)))
{
pf.dwRGBAlphaBitMask = 0;
}
}
void returnSurface(const Surface& surface)
{
if (!surface.surface)
{
return;
}
if (surface.desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
{
g_sysMemRepo.surfaces.push_back(surface);
}
else
{
g_vidMemRepos[surface.ddObject].surfaces.push_back(surface);
}
}
}
namespace DDraw
{
namespace Repository
{
ScopedSurface::ScopedSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc)
: Surface(getSurface(dd, desc))
{
if (surface)
{
surface->SetColorKey(surface, DDCKEY_SRCBLT, nullptr);
surface->SetColorKey(surface, DDCKEY_DESTBLT, nullptr);
}
}
ScopedSurface::~ScopedSurface()
{
returnSurface(*this);
}
CompatWeakPtr<IDirectDraw7> getDirectDraw()
{
static auto dd = new CompatPtr<IDirectDraw7>(createDirectDraw());
return *dd;
}
void onRelease(void* ddObject)
{
auto it = g_vidMemRepos.find(ddObject);
if (it != g_vidMemRepos.end())
{
for (auto& surface : it->second.surfaces)
{
surface.surface->Release(surface.surface);
}
g_vidMemRepos.erase(it);
}
}
}
}

View File

@ -1,29 +0,0 @@
#pragma once
#include <ddraw.h>
#include "Common/CompatRef.h"
#include "Common/CompatWeakPtr.h"
namespace DDraw
{
namespace Repository
{
struct Surface
{
void* ddObject;
DDSURFACEDESC2 desc;
CompatWeakPtr<IDirectDrawSurface7> surface;
};
class ScopedSurface : public Surface
{
public:
ScopedSurface(CompatRef<IDirectDraw7> dd, const DDSURFACEDESC2& desc);
~ScopedSurface();
};
CompatWeakPtr<IDirectDraw7> getDirectDraw();
void onRelease(void* ddObject);
}
}

View File

@ -47,7 +47,7 @@ namespace
}
CompatPtr<IDirectDrawClipper> gdiClipper;
CALL_ORIG_PROC(DirectDrawCreateClipper, 0, &gdiClipper.getRef(), nullptr);
CALL_ORIG_PROC(DirectDrawCreateClipper)(0, &gdiClipper.getRef(), nullptr);
if (!gdiClipper)
{
return;
@ -68,13 +68,6 @@ namespace
{
caps &= ~DDSCAPS_OFFSCREENPLAIN;
caps |= DDSCAPS_PRIMARYSURFACE | DDSCAPS_VISIBLE;
if ((caps & DDSCAPS_SYSTEMMEMORY) &&
!(DDraw::PrimarySurface::getOrigCaps() & DDSCAPS_SYSTEMMEMORY))
{
caps &= ~DDSCAPS_SYSTEMMEMORY;
caps |= DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
}
}
}

View File

@ -13,28 +13,6 @@ DEFINE_GUID(IID_CompatSurfacePrivateData,
namespace
{
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
HRESULT createSurface(CompatRef<TDirectDraw> dd, TSurfaceDesc desc, TSurface*& surface)
{
fixSurfaceDesc(desc.dwFlags, desc.ddsCaps.dwCaps, desc.ddpfPixelFormat);
if ((desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) &&
!(desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY | DDSCAPS_3DDEVICE)))
{
TSurfaceDesc sysMemDesc = desc;
sysMemDesc.ddsCaps.dwCaps &=
~(DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
sysMemDesc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
if (SUCCEEDED(dd->CreateSurface(&dd, &sysMemDesc, &surface, nullptr)))
{
return DD_OK;
}
}
return dd->CreateSurface(&dd, &desc, &surface, nullptr);
}
void fixSurfaceDesc(DWORD& flags, DWORD& caps, DDPIXELFORMAT& pf)
{
if ((flags & DDSD_WIDTH) &&
@ -47,12 +25,6 @@ namespace
pf = DDraw::getRgbPixelFormat(Win32::DisplayMode::getBpp());
}
if ((pf.dwFlags & DDPF_RGB) && pf.dwRGBBitCount <= 8)
{
caps &= ~(DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
caps |= DDSCAPS_SYSTEMMEMORY;
}
if (!(caps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_OVERLAY | DDSCAPS_TEXTURE |
DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)))
{
@ -157,7 +129,9 @@ namespace DDraw
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
HRESULT Surface::create(CompatRef<TDirectDraw> dd, TSurfaceDesc desc, TSurface*& surface)
{
HRESULT result = createSurface(dd, desc, surface);
fixSurfaceDesc(desc.dwFlags, desc.ddsCaps.dwCaps, desc.ddpfPixelFormat);
HRESULT result = dd->CreateSurface(&dd, &desc, &surface, nullptr);
if (SUCCEEDED(result))
{
CompatPtr<IDirectDrawSurface7> surface7(

View File

@ -1,8 +1,6 @@
#include <set>
#include "Common/CompatRef.h"
#include "DDraw/RealPrimarySurface.h"
#include "DDraw/Repository.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "DDraw/Surfaces/Surface.h"
#include "DDraw/Surfaces/SurfaceImpl.h"
@ -20,16 +18,6 @@ namespace
DWORD unknown2;
};
template <typename TSurface>
void copyColorKey(CompatRef<TSurface> dst, CompatRef<TSurface> src, DWORD ckFlag)
{
DDCOLORKEY ck = {};
if (SUCCEEDED(src->GetColorKey(&src, ckFlag, &ck)))
{
dst->SetColorKey(&dst, ckFlag, &ck);
}
}
template <typename TSurface>
bool waitForFlip(TSurface* This, DWORD flags, DWORD waitFlag, DWORD doNotWaitFlag)
{
@ -52,105 +40,6 @@ namespace DDraw
{
}
template <typename TSurface>
bool SurfaceImpl<TSurface>::bltRetry(TSurface*& dstSurface, RECT*& dstRect,
TSurface*& srcSurface, RECT*& srcRect, bool isTransparentBlt,
const std::function<HRESULT()>& blt)
{
if (!dstSurface || !srcSurface)
{
return false;
}
TSurfaceDesc dstDesc = {};
dstDesc.dwSize = sizeof(dstDesc);
s_origVtable.GetSurfaceDesc(dstSurface, &dstDesc);
TSurfaceDesc srcDesc = {};
srcDesc.dwSize = sizeof(srcDesc);
s_origVtable.GetSurfaceDesc(srcSurface, &srcDesc);
if ((dstDesc.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
(dstDesc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
(srcDesc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
{
const bool isCopyNeeded = true;
return prepareBltRetrySurface(srcSurface, srcRect, srcDesc, isTransparentBlt, isCopyNeeded) &&
SUCCEEDED(blt());
}
else if ((srcDesc.ddpfPixelFormat.dwFlags & DDPF_FOURCC) &&
(srcDesc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) &&
(dstDesc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY))
{
TSurface* origDstSurface = dstSurface;
RECT* origDstRect = dstRect;
const bool isCopyNeeded = isTransparentBlt;
return prepareBltRetrySurface(dstSurface, dstRect, dstDesc, isTransparentBlt, isCopyNeeded) &&
SUCCEEDED(blt()) &&
SUCCEEDED(s_origVtable.Blt(
origDstSurface, origDstRect, dstSurface, dstRect, DDBLT_WAIT, nullptr));
}
return false;
}
template <typename TSurface>
bool SurfaceImpl<TSurface>::prepareBltRetrySurface(TSurface*& surface, RECT*& rect,
const TSurfaceDesc& desc, bool isTransparentBlt, bool isCopyNeeded)
{
TSurface* replSurface = surface;
RECT* replRect = rect;
replaceWithVidMemSurface(replSurface, replRect, desc);
if (replSurface == surface)
{
return false;
}
if (isCopyNeeded && FAILED(s_origVtable.Blt(
replSurface, replRect, surface, rect, DDBLT_WAIT, nullptr)))
{
return false;
}
if (isTransparentBlt)
{
copyColorKey<TSurface>(*replSurface, *surface, DDCKEY_SRCBLT);
copyColorKey<TSurface>(*replSurface, *surface, DDCKEY_DESTBLT);
}
surface = replSurface;
rect = replRect;
return true;
}
template <typename TSurface>
void SurfaceImpl<TSurface>::replaceWithVidMemSurface(TSurface*& surface, RECT*& rect,
const TSurfaceDesc& desc)
{
static RECT replRect = {};
replRect = rect ? RECT{ 0, 0, rect->right - rect->left, rect->bottom - rect->top } :
RECT{ 0, 0, static_cast<LONG>(desc.dwWidth), static_cast<LONG>(desc.dwHeight) };
DDSURFACEDESC2 replDesc = {};
replDesc.dwSize = sizeof(replDesc);
replDesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
replDesc.dwWidth = replRect.right;
replDesc.dwHeight = replRect.bottom;
replDesc.ddpfPixelFormat = desc.ddpfPixelFormat;
replDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
CompatPtr<IUnknown> ddUnk;
GetDDInterface(surface, reinterpret_cast<void**>(&ddUnk.getRef()));
CompatPtr<IDirectDraw7> dd;
ddUnk->QueryInterface(ddUnk, IID_IDirectDraw7, reinterpret_cast<void**>(&dd.getRef()));
DDraw::Repository::ScopedSurface replacementSurface(*dd, replDesc);
if (replacementSurface.surface)
{
surface = CompatPtr<TSurface>::from(replacementSurface.surface.get());
rect = &replRect;
}
}
template <typename TSurface>
HRESULT SurfaceImpl<TSurface>::Blt(
TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
@ -163,19 +52,7 @@ namespace DDraw
Gdi::DDrawAccessGuard dstAccessGuard(Gdi::ACCESS_WRITE, PrimarySurface::isGdiSurface(This));
Gdi::DDrawAccessGuard srcAccessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(lpDDSrcSurface));
HRESULT result = s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
if (DDERR_UNSUPPORTED == result || DDERR_GENERIC == result)
{
const bool isTransparentBlt = 0 !=
(dwFlags & (DDBLT_KEYDEST | DDBLT_KEYSRC | DDBLT_KEYDESTOVERRIDE | DDBLT_KEYSRCOVERRIDE));
if (bltRetry(This, lpDestRect, lpDDSrcSurface, lpSrcRect, isTransparentBlt,
[&]() { return s_origVtable.Blt(
This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); }))
{
return DD_OK;
}
}
return result;
return s_origVtable.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
}
template <typename TSurface>
@ -189,35 +66,7 @@ namespace DDraw
Gdi::DDrawAccessGuard dstAccessGuard(Gdi::ACCESS_WRITE, PrimarySurface::isGdiSurface(This));
Gdi::DDrawAccessGuard srcAccessGuard(Gdi::ACCESS_READ, PrimarySurface::isGdiSurface(lpDDSrcSurface));
HRESULT result = s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
if (DDERR_UNSUPPORTED == result || DDERR_GENERIC == result)
{
RECT dstRect = { static_cast<LONG>(dwX), static_cast<LONG>(dwY) };
if (lpSrcRect)
{
dstRect.right = dwX + lpSrcRect->right - lpSrcRect->left;
dstRect.bottom = dwY + lpSrcRect->bottom - lpSrcRect->top;
}
else
{
TSurfaceDesc desc = {};
desc.dwSize = sizeof(desc);
s_origVtable.GetSurfaceDesc(lpDDSrcSurface, &desc);
dstRect.right = dwX + desc.dwWidth;
dstRect.bottom = dwY + desc.dwHeight;
}
RECT* dstRectPtr = &dstRect;
const bool isTransparentBlt = 0 != (dwTrans & (DDBLTFAST_DESTCOLORKEY | DDBLTFAST_SRCCOLORKEY));
if (bltRetry(This, dstRectPtr, lpDDSrcSurface, lpSrcRect, isTransparentBlt,
[&]() { return s_origVtable.BltFast(
This, dstRectPtr->left, dstRectPtr->top, lpDDSrcSurface, lpSrcRect, dwTrans); }))
{
return DD_OK;
}
}
return result;
return s_origVtable.BltFast(This, dwX, dwY, lpDDSrcSurface, lpSrcRect, dwTrans);
}
template <typename TSurface>

View File

@ -55,13 +55,5 @@ namespace DDraw
protected:
static const Vtable<TSurface>& s_origVtable;
private:
bool bltRetry(TSurface*& dstSurface, RECT*& dstRect,
TSurface*& srcSurface, RECT*& srcRect, bool isTransparentBlt,
const std::function<HRESULT()>& blt);
bool prepareBltRetrySurface(TSurface*& surface, RECT*& rect,
const TSurfaceDesc& desc, bool isTransparentBlt, bool isCopyNeeded);
void replaceWithVidMemSurface(TSurface*& surface, RECT*& rect, const TSurfaceDesc& desc);
};
}

View File

@ -269,7 +269,6 @@
<ClInclude Include="DDraw\DirectDrawPalette.h" />
<ClInclude Include="DDraw\DirectDrawSurface.h" />
<ClInclude Include="DDraw\Hooks.h" />
<ClInclude Include="DDraw\Repository.h" />
<ClInclude Include="DDraw\ScopedThreadLock.h" />
<ClInclude Include="DDraw\Surfaces\PrimarySurface.h" />
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h" />
@ -342,7 +341,6 @@
<ClCompile Include="DDraw\DirectDrawPalette.cpp" />
<ClCompile Include="DDraw\DirectDrawSurface.cpp" />
<ClCompile Include="DDraw\Hooks.cpp" />
<ClCompile Include="DDraw\Repository.cpp" />
<ClCompile Include="DDraw\IReleaseNotifier.cpp" />
<ClCompile Include="DDraw\RealPrimarySurface.cpp" />
<ClCompile Include="DDraw\Surfaces\PrimarySurface.cpp" />

View File

@ -123,9 +123,6 @@
<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>
@ -392,9 +389,6 @@
<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>

View File

@ -1,23 +1,17 @@
#include <functional>
#include <d3d.h>
#include "Common/CompatPtr.h"
#include "Common/CompatRef.h"
#include "Common/Log.h"
#include "DDraw/Repository.h"
#include "Direct3d/Direct3d.h"
#include "Direct3d/Direct3dDevice.h"
#include "Direct3d/Direct3dTexture.h"
#include "Direct3d/Direct3dVertexBuffer.h"
#include "Direct3d/Direct3dViewport.h"
#include "Direct3d/Hooks.h"
#include "Dll/Procs.h"
namespace
{
void hookDirect3dDevice(CompatRef<IDirect3D3> d3d, CompatRef<IDirectDrawSurface4> renderTarget);
void hookDirect3dDevice7(CompatRef<IDirect3D7> d3d, CompatRef<IDirectDrawSurface7> renderTarget);
void hookDirect3dTexture(CompatRef<IDirectDraw> dd);
void hookDirect3dVertexBuffer(CompatRef<IDirect3D3> d3d);
void hookDirect3dVertexBuffer7(CompatRef<IDirect3D7> d3d);
@ -56,7 +50,7 @@ namespace
desc.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
desc.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
desc.ddpfPixelFormat.dwBBitMask = 0x000000FF;
desc.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY;
desc.ddsCaps.dwCaps = DDSCAPS_3DDEVICE;
CompatPtr<IDirectDrawSurface7> renderTarget;
HRESULT result = dd->CreateSurface(&dd, &desc, &renderTarget.getRef(), nullptr);
@ -187,17 +181,8 @@ namespace
namespace Direct3d
{
void installHooks()
void installHooks(CompatPtr<IDirectDraw> dd, CompatPtr<IDirectDraw7> dd7)
{
auto dd7(DDraw::Repository::getDirectDraw());
CompatPtr<IDirectDraw> dd;
CALL_ORIG_PROC(DirectDrawCreate, nullptr, &dd.getRef(), nullptr);
if (!dd || !dd7 || FAILED(dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL)))
{
Compat::Log() << "ERROR: Failed to hook Direct3d interfaces";
return;
}
CompatPtr<IDirectDrawSurface7> renderTarget7(createRenderTarget(*dd7));
if (renderTarget7)
{

View File

@ -1,6 +1,10 @@
#pragma once
#include <ddraw.h>
#include "Common/CompatPtr.h"
namespace Direct3d
{
void installHooks();
void installHooks(CompatPtr<IDirectDraw> dd, CompatPtr<IDirectDraw7> dd7);
}

View File

@ -43,10 +43,32 @@ namespace
Compat::Log() << "Installing display mode hooks";
Win32::DisplayMode::installHooks(g_origDDrawModule);
Gdi::VirtualScreen::init();
CompatPtr<IDirectDraw> dd;
CALL_ORIG_PROC(DirectDrawCreate)(nullptr, &dd.getRef(), nullptr);
CompatPtr<IDirectDraw> dd7;
CALL_ORIG_PROC(DirectDrawCreateEx)(nullptr, reinterpret_cast<void**>(&dd7.getRef()), IID_IDirectDraw7, nullptr);
if (!dd || !dd7)
{
Compat::Log() << "ERROR: Failed to create a DirectDraw object for hooking";
return;
}
HRESULT result = dd->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL);
if (SUCCEEDED(result))
{
dd7->SetCooperativeLevel(dd7, nullptr, DDSCL_NORMAL);
}
if (FAILED(result))
{
Compat::Log() << "ERROR: Failed to set the cooperative level for hooking: " << Compat::hex(result);
return;
}
Compat::Log() << "Installing DirectDraw hooks";
DDraw::installHooks();
DDraw::installHooks(dd7);
Compat::Log() << "Installing Direct3D hooks";
Direct3d::installHooks();
Direct3d::installHooks(dd, dd7);
Compat::Log() << "Installing GDI hooks";
Gdi::installHooks();
Compat::Log() << "Finished installing hooks";
@ -133,7 +155,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Time::init();
const DWORD disableMaxWindowedMode = 12;
CALL_ORIG_PROC(SetAppCompatData, disableMaxWindowedMode, 0);
CALL_ORIG_PROC(SetAppCompatData)(disableMaxWindowedMode, 0);
Compat::Log() << "DDrawCompat loaded successfully";
}
@ -169,7 +191,7 @@ extern "C" HRESULT WINAPI DirectDrawCreate(
LOG_FUNC(__func__, lpGUID, lplpDD, pUnkOuter);
installHooks();
DDraw::suppressEmulatedDirectDraw(lpGUID);
return LOG_RESULT(CALL_ORIG_PROC(DirectDrawCreate, lpGUID, lplpDD, pUnkOuter));
return LOG_RESULT(CALL_ORIG_PROC(DirectDrawCreate)(lpGUID, lplpDD, pUnkOuter));
}
extern "C" HRESULT WINAPI DirectDrawCreateEx(
@ -181,7 +203,7 @@ extern "C" HRESULT WINAPI DirectDrawCreateEx(
LOG_FUNC(__func__, lpGUID, lplpDD, iid, pUnkOuter);
installHooks();
DDraw::suppressEmulatedDirectDraw(lpGUID);
return LOG_RESULT(CALL_ORIG_PROC(DirectDrawCreateEx, lpGUID, lplpDD, iid, pUnkOuter));
return LOG_RESULT(CALL_ORIG_PROC(DirectDrawCreateEx)(lpGUID, lplpDD, iid, pUnkOuter));
}
extern "C" HRESULT WINAPI DirectInputCreateA(
@ -191,7 +213,7 @@ extern "C" HRESULT WINAPI DirectInputCreateA(
LPUNKNOWN punkOuter)
{
LOG_FUNC(__func__, hinst, dwVersion, lplpDirectInput, punkOuter);
return LOG_RESULT(CALL_ORIG_PROC(DirectInputCreateA, hinst, dwVersion, lplpDirectInput, punkOuter));
return LOG_RESULT(CALL_ORIG_PROC(DirectInputCreateA)(hinst, dwVersion, lplpDirectInput, punkOuter));
}
extern "C" HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
@ -199,5 +221,5 @@ extern "C" HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID
LOG_FUNC(__func__, rclsid, riid, ppv);
LOG_ONCE("COM instantiation of DirectDraw detected");
installHooks();
return LOG_RESULT(CALL_ORIG_PROC(DllGetClassObject, rclsid, riid, ppv));
return LOG_RESULT(CALL_ORIG_PROC(DllGetClassObject)(rclsid, riid, ppv));
}

View File

@ -49,7 +49,4 @@ namespace Dll
#undef ADD_FARPROC_MEMBER
#define CALL_ORIG_PROC(procName, ...) \
(Dll::g_origProcs.procName ? \
reinterpret_cast<decltype(procName)*>(Dll::g_origProcs.procName)(__VA_ARGS__) : \
E_FAIL)
#define CALL_ORIG_PROC(procName) reinterpret_cast<decltype(procName)*>(Dll::g_origProcs.procName)