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:
parent
5b171691f0
commit
26f8742dc2
@ -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"
|
||||
|
||||
|
@ -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);
|
||||
|
@ -1,7 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
void installHooks();
|
||||
void installHooks(CompatPtr<IDirectDraw7> dd7);
|
||||
void uninstallHooks();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user