mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Added support for Steam overlay in fullscreen mode
This commit is contained in:
parent
f1f775aaa4
commit
79d2eea9e3
@ -105,28 +105,6 @@ namespace
|
|||||||
return ntHeaders;
|
return ntHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getInstructionSize(void* instruction)
|
|
||||||
{
|
|
||||||
const unsigned MAX_INSTRUCTION_SIZE = 15;
|
|
||||||
HRESULT result = g_debugDataSpaces->WriteVirtual(g_debugBase, instruction, MAX_INSTRUCTION_SIZE, nullptr);
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
LOG_ONCE("ERROR: DbgEng: WriteVirtual failed: " << Compat::hex(result));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG64 endOffset = 0;
|
|
||||||
result = g_debugControl->Disassemble(g_debugBase, 0, nullptr, 0, nullptr, &endOffset);
|
|
||||||
if (FAILED(result))
|
|
||||||
{
|
|
||||||
LOG_ONCE("ERROR: DbgEng: Disassemble failed: " << Compat::hex(result) << " "
|
|
||||||
<< Compat::hexDump(instruction, MAX_INSTRUCTION_SIZE));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<unsigned>(endOffset - g_debugBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hookFunction(void*& origFuncPtr, void* newFuncPtr, const char* funcName)
|
void hookFunction(void*& origFuncPtr, void* newFuncPtr, const char* funcName)
|
||||||
{
|
{
|
||||||
BYTE* targetFunc = static_cast<BYTE*>(origFuncPtr);
|
BYTE* targetFunc = static_cast<BYTE*>(origFuncPtr);
|
||||||
@ -193,7 +171,7 @@ namespace
|
|||||||
BYTE* dst = trampoline;
|
BYTE* dst = trampoline;
|
||||||
while (src - targetFunc < 5)
|
while (src - targetFunc < 5)
|
||||||
{
|
{
|
||||||
unsigned instructionSize = getInstructionSize(src);
|
unsigned instructionSize = Compat::getInstructionSize(src);
|
||||||
if (0 == instructionSize)
|
if (0 == instructionSize)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -223,13 +201,12 @@ namespace
|
|||||||
memset(targetFunc + 5, 0xCC, src - targetFunc - 5);
|
memset(targetFunc + 5, 0xCC, src - targetFunc - 5);
|
||||||
VirtualProtect(targetFunc, src - targetFunc, PAGE_EXECUTE_READ, &oldProtect);
|
VirtualProtect(targetFunc, src - targetFunc, PAGE_EXECUTE_READ, &oldProtect);
|
||||||
|
|
||||||
FlushInstructionCache(GetCurrentProcess(), nullptr, 0);
|
origFuncPtr = trampoline;
|
||||||
|
CALL_ORIG_FUNC(FlushInstructionCache)(GetCurrentProcess(), nullptr, 0);
|
||||||
|
|
||||||
HMODULE module = nullptr;
|
HMODULE module = nullptr;
|
||||||
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
|
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN,
|
||||||
reinterpret_cast<char*>(targetFunc), &module);
|
reinterpret_cast<char*>(targetFunc), &module);
|
||||||
|
|
||||||
origFuncPtr = trampoline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool initDbgEng()
|
bool initDbgEng()
|
||||||
@ -339,7 +316,7 @@ namespace Compat
|
|||||||
g_isDbgEngInitialized = false;
|
g_isDbgEngInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string funcPtrToStr(void* funcPtr)
|
std::string funcPtrToStr(const void* funcPtr)
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
HMODULE module = Compat::getModuleHandleFromAddress(funcPtr);
|
HMODULE module = Compat::getModuleHandleFromAddress(funcPtr);
|
||||||
@ -355,11 +332,63 @@ namespace Compat
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
HMODULE getModuleHandleFromAddress(void* address)
|
unsigned getInstructionSize(void* instruction)
|
||||||
|
{
|
||||||
|
const unsigned MAX_INSTRUCTION_SIZE = 15;
|
||||||
|
HRESULT result = g_debugDataSpaces->WriteVirtual(g_debugBase, instruction, MAX_INSTRUCTION_SIZE, nullptr);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
LOG_ONCE("ERROR: DbgEng: WriteVirtual failed: " << Compat::hex(result));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG64 endOffset = 0;
|
||||||
|
result = g_debugControl->Disassemble(g_debugBase, 0, nullptr, 0, nullptr, &endOffset);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
LOG_ONCE("ERROR: DbgEng: Disassemble failed: " << Compat::hex(result) << " "
|
||||||
|
<< Compat::hexDump(instruction, MAX_INSTRUCTION_SIZE));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<unsigned>(endOffset - g_debugBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD getModuleFileOffset(const void* address)
|
||||||
|
{
|
||||||
|
LOG_FUNC("getModuleFileOffset", address);
|
||||||
|
HMODULE mod = getModuleHandleFromAddress(address);
|
||||||
|
if (!mod)
|
||||||
|
{
|
||||||
|
return LOG_RESULT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
PIMAGE_NT_HEADERS ntHeaders = getImageNtHeaders(mod);
|
||||||
|
if (!ntHeaders)
|
||||||
|
{
|
||||||
|
return LOG_RESULT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD offset = static_cast<const BYTE*>(address) - reinterpret_cast<const BYTE*>(mod);
|
||||||
|
auto sectionHeader = reinterpret_cast<IMAGE_SECTION_HEADER*>(
|
||||||
|
&ntHeaders->OptionalHeader.DataDirectory[ntHeaders->OptionalHeader.NumberOfRvaAndSizes]);
|
||||||
|
for (unsigned i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
|
||||||
|
{
|
||||||
|
if (offset >= sectionHeader->VirtualAddress &&
|
||||||
|
offset < sectionHeader->VirtualAddress + sectionHeader->SizeOfRawData)
|
||||||
|
{
|
||||||
|
return LOG_RESULT(sectionHeader->PointerToRawData + offset - sectionHeader->VirtualAddress);
|
||||||
|
}
|
||||||
|
sectionHeader++;
|
||||||
|
}
|
||||||
|
return LOG_RESULT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE getModuleHandleFromAddress(const void* address)
|
||||||
{
|
{
|
||||||
HMODULE module = nullptr;
|
HMODULE module = nullptr;
|
||||||
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||||
static_cast<char*>(address), &module);
|
static_cast<const char*>(address), &module);
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,8 +14,10 @@
|
|||||||
namespace Compat
|
namespace Compat
|
||||||
{
|
{
|
||||||
void closeDbgEng();
|
void closeDbgEng();
|
||||||
std::string funcPtrToStr(void* funcPtr);
|
std::string funcPtrToStr(const void* funcPtr);
|
||||||
HMODULE getModuleHandleFromAddress(void* address);
|
unsigned getInstructionSize(void* instruction);
|
||||||
|
DWORD getModuleFileOffset(const void* address);
|
||||||
|
HMODULE getModuleHandleFromAddress(const void* address);
|
||||||
|
|
||||||
template <auto origFunc>
|
template <auto origFunc>
|
||||||
decltype(origFunc) g_origFuncPtr = origFunc;
|
decltype(origFunc) g_origFuncPtr = origFunc;
|
||||||
|
@ -58,6 +58,8 @@ namespace D3dDdi
|
|||||||
, m_origVtable(CompatVtable<D3DDDI_ADAPTERFUNCS>::s_origVtable)
|
, m_origVtable(CompatVtable<D3DDDI_ADAPTERFUNCS>::s_origVtable)
|
||||||
, m_runtimeVersion(data.Version)
|
, m_runtimeVersion(data.Version)
|
||||||
, m_driverVersion(data.DriverVersion)
|
, m_driverVersion(data.DriverVersion)
|
||||||
|
, m_guid(nullptr)
|
||||||
|
, m_guidBuf{}
|
||||||
, m_luid(KernelModeThunks::getLastOpenAdapterInfo().luid)
|
, m_luid(KernelModeThunks::getLastOpenAdapterInfo().luid)
|
||||||
, m_deviceName(KernelModeThunks::getLastOpenAdapterInfo().deviceName)
|
, m_deviceName(KernelModeThunks::getLastOpenAdapterInfo().deviceName)
|
||||||
, m_repository{}
|
, m_repository{}
|
||||||
@ -496,19 +498,20 @@ namespace D3dDdi
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Adapter::setRepository(LUID luid, CompatWeakPtr<IDirectDraw7> repository, bool isPrimary)
|
void Adapter::setRepository(LUID luid, GUID* guid, CompatWeakPtr<IDirectDraw7> repository)
|
||||||
{
|
{
|
||||||
for (auto& adapter : s_adapters)
|
for (auto& adapter : s_adapters)
|
||||||
{
|
{
|
||||||
if (adapter.second.m_luid == luid)
|
if (adapter.second.m_luid == luid)
|
||||||
{
|
{
|
||||||
|
if (guid)
|
||||||
|
{
|
||||||
|
adapter.second.m_guidBuf = *guid;
|
||||||
|
adapter.second.m_guid = &adapter.second.m_guidBuf;
|
||||||
|
}
|
||||||
adapter.second.m_repository = repository;
|
adapter.second.m_repository = repository;
|
||||||
auto& surfaceRepo = SurfaceRepository::get(adapter.second);
|
auto& surfaceRepo = SurfaceRepository::get(adapter.second);
|
||||||
surfaceRepo.setRepository(repository);
|
surfaceRepo.setRepository(repository);
|
||||||
if (isPrimary)
|
|
||||||
{
|
|
||||||
surfaceRepo.setAsPrimaryRepo();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ namespace D3dDdi
|
|||||||
operator HANDLE() const { return m_adapter; }
|
operator HANDLE() const { return m_adapter; }
|
||||||
|
|
||||||
SIZE getAspectRatio() const;
|
SIZE getAspectRatio() const;
|
||||||
|
GUID* getGuid() const { return m_guid; }
|
||||||
const AdapterInfo& getInfo() const { return m_info; }
|
const AdapterInfo& getInfo() const { return m_info; }
|
||||||
LUID getLuid() const { return m_luid; }
|
LUID getLuid() const { return m_luid; }
|
||||||
const auto& getMonitorInfo() const { return Win32::DisplayMode::getMonitorInfo(m_deviceName); }
|
const auto& getMonitorInfo() const { return Win32::DisplayMode::getMonitorInfo(m_deviceName); }
|
||||||
@ -53,7 +54,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
static void add(const D3DDDIARG_OPENADAPTER& data) { s_adapters.emplace(data.hAdapter, data); }
|
static void add(const D3DDDIARG_OPENADAPTER& data) { s_adapters.emplace(data.hAdapter, data); }
|
||||||
static Adapter& get(HANDLE adapter) { return s_adapters.find(adapter)->second; }
|
static Adapter& get(HANDLE adapter) { return s_adapters.find(adapter)->second; }
|
||||||
static void setRepository(LUID luid, CompatWeakPtr<IDirectDraw7> repository, bool isPrimary);
|
static void setRepository(LUID luid, GUID* guid, CompatWeakPtr<IDirectDraw7> repository);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const AdapterInfo& findInfo() const;
|
const AdapterInfo& findInfo() const;
|
||||||
@ -74,6 +75,8 @@ namespace D3dDdi
|
|||||||
D3DDDI_ADAPTERFUNCS m_origVtable;
|
D3DDDI_ADAPTERFUNCS m_origVtable;
|
||||||
UINT m_runtimeVersion;
|
UINT m_runtimeVersion;
|
||||||
UINT m_driverVersion;
|
UINT m_driverVersion;
|
||||||
|
GUID* m_guid;
|
||||||
|
GUID m_guidBuf;
|
||||||
LUID m_luid;
|
LUID m_luid;
|
||||||
std::wstring m_deviceName;
|
std::wstring m_deviceName;
|
||||||
CompatWeakPtr<IDirectDraw7> m_repository;
|
CompatWeakPtr<IDirectDraw7> m_repository;
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <D3dDdi/Log/DeviceFuncsLog.h>
|
#include <D3dDdi/Log/DeviceFuncsLog.h>
|
||||||
#include <D3dDdi/Resource.h>
|
#include <D3dDdi/Resource.h>
|
||||||
#include <D3dDdi/ShaderAssembler.h>
|
#include <D3dDdi/ShaderAssembler.h>
|
||||||
|
#include <Overlay/Steam.h>
|
||||||
#include <Shaders/VertexFixup.h>
|
#include <Shaders/VertexFixup.h>
|
||||||
|
|
||||||
#define LOG_DS LOG_DEBUG << "DeviceState::" << __func__ << ": "
|
#define LOG_DS LOG_DEBUG << "DeviceState::" << __func__ << ": "
|
||||||
@ -1117,7 +1118,19 @@ namespace D3dDdi
|
|||||||
auto depthStencil = m_app.depthStencil;
|
auto depthStencil = m_app.depthStencil;
|
||||||
bool isTransformed = getVertexDecl().isTransformed;
|
bool isTransformed = getVertexDecl().isTransformed;
|
||||||
|
|
||||||
Resource* resource = m_device.getResource(renderTarget.hRenderTarget);
|
Resource* resource = nullptr;
|
||||||
|
auto steamResources = Overlay::Steam::getResources();
|
||||||
|
if (steamResources.bbResource && *steamResources.rtResource == renderTarget.hRenderTarget)
|
||||||
|
{
|
||||||
|
resource = steamResources.bbResource;
|
||||||
|
renderTarget.hRenderTarget = *steamResources.bbResource;
|
||||||
|
renderTarget.SubResourceIndex = steamResources.bbSubResourceIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resource = m_device.getResource(renderTarget.hRenderTarget);
|
||||||
|
}
|
||||||
|
|
||||||
if (resource)
|
if (resource)
|
||||||
{
|
{
|
||||||
auto customResource = resource->getCustomResource();
|
auto customResource = resource->getCustomResource();
|
||||||
@ -1129,11 +1142,11 @@ namespace D3dDdi
|
|||||||
if (isTransformed)
|
if (isTransformed)
|
||||||
{
|
{
|
||||||
scissorRect = makeRect(scaledVp);
|
scissorRect = makeRect(scaledVp);
|
||||||
auto& si = resource->getOrigDesc().pSurfList[renderTarget.SubResourceIndex];
|
auto& si = resource->getFixedDesc().pSurfList[renderTarget.SubResourceIndex];
|
||||||
vp = { 0, 0, si.Width, si.Height };
|
vp = { 0, 0, si.Width, si.Height };
|
||||||
if (customResource)
|
if (customResource)
|
||||||
{
|
{
|
||||||
auto& scaledSi = customResource->getOrigDesc().pSurfList[renderTarget.SubResourceIndex];
|
auto& scaledSi = customResource->getFixedDesc().pSurfList[renderTarget.SubResourceIndex];
|
||||||
scaledVp = { 0, 0, scaledSi.Width, scaledSi.Height };
|
scaledVp = { 0, 0, scaledSi.Width, scaledSi.Height };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -273,6 +273,27 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETVERTEXSHADERCONST&
|
|||||||
<< val.Count;
|
<< val.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXBLT& val)
|
||||||
|
{
|
||||||
|
return Compat::LogStruct(os)
|
||||||
|
<< val.hDstResource
|
||||||
|
<< val.hSrcResource
|
||||||
|
<< val.CubeMapFace
|
||||||
|
<< val.DstPoint
|
||||||
|
<< val.SrcRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXBLT1& val)
|
||||||
|
{
|
||||||
|
return Compat::LogStruct(os)
|
||||||
|
<< val.hDstResource
|
||||||
|
<< val.hSrcResource
|
||||||
|
<< val.CubeMapFace
|
||||||
|
<< val.DstPoint
|
||||||
|
<< val.SrcRect
|
||||||
|
<< Compat::hex(val.CopyFlags);
|
||||||
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXTURESTAGESTATE& val)
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXTURESTAGESTATE& val)
|
||||||
{
|
{
|
||||||
return Compat::LogStruct(os)
|
return Compat::LogStruct(os)
|
||||||
|
@ -34,6 +34,8 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETRENDERTARGET& val)
|
|||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCE& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCE& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCEUM& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCEUM& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETVERTEXSHADERCONST& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETVERTEXSHADERCONST& val);
|
||||||
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXBLT& val);
|
||||||
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXBLT1& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXTURESTAGESTATE& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXTURESTAGESTATE& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val);
|
||||||
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UPDATEPALETTE& val);
|
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UPDATEPALETTE& val);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <Gdi/Palette.h>
|
#include <Gdi/Palette.h>
|
||||||
#include <Gdi/VirtualScreen.h>
|
#include <Gdi/VirtualScreen.h>
|
||||||
#include <Gdi/Window.h>
|
#include <Gdi/Window.h>
|
||||||
|
#include <Overlay/Steam.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -244,7 +245,14 @@ namespace D3dDdi
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldBltViaCpu(data, *srcResource))
|
auto steamResources = Overlay::Steam::getResources();
|
||||||
|
if (steamResources.rtResource == srcResource && steamResources.bbResource)
|
||||||
|
{
|
||||||
|
srcResource = steamResources.bbResource;
|
||||||
|
data.hSrcResource = *steamResources.bbResource;
|
||||||
|
data.SrcSubResourceIndex = steamResources.bbSubResourceIndex;
|
||||||
|
}
|
||||||
|
else if (shouldBltViaCpu(data, *srcResource))
|
||||||
{
|
{
|
||||||
return bltViaCpu(data, *srcResource);
|
return bltViaCpu(data, *srcResource);
|
||||||
}
|
}
|
||||||
@ -1014,7 +1022,7 @@ namespace D3dDdi
|
|||||||
|
|
||||||
HRESULT Resource::lock(D3DDDIARG_LOCK& data)
|
HRESULT Resource::lock(D3DDDIARG_LOCK& data)
|
||||||
{
|
{
|
||||||
if (D3DDDIMULTISAMPLE_NONE != m_fixedData.MultisampleType)
|
if (D3DDDIMULTISAMPLE_NONE != m_fixedData.MultisampleType || FOURCC_NULL == m_fixedData.Format)
|
||||||
{
|
{
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
@ -1325,6 +1333,8 @@ namespace D3dDdi
|
|||||||
presentLayeredWindows(*this, data.DstSubResourceIndex, getRect(data.DstSubResourceIndex),
|
presentLayeredWindows(*this, data.DstSubResourceIndex, getRect(data.DstSubResourceIndex),
|
||||||
Gdi::Window::getVisibleOverlayWindows(), m_device.getAdapter().getMonitorInfo().rcMonitor);
|
Gdi::Window::getVisibleOverlayWindows(), m_device.getAdapter().getMonitorInfo().rcMonitor);
|
||||||
|
|
||||||
|
Overlay::Steam::render(*this, data.DstSubResourceIndex);
|
||||||
|
|
||||||
return LOG_RESULT(S_OK);
|
return LOG_RESULT(S_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,9 +431,13 @@ namespace D3dDdi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceRepository::setAsPrimaryRepo()
|
void SurfaceRepository::setRepository(CompatWeakPtr<IDirectDraw7> dd)
|
||||||
{
|
{
|
||||||
g_primaryRepository = this;
|
m_dd = dd;
|
||||||
|
if (!g_primaryRepository)
|
||||||
|
{
|
||||||
|
g_primaryRepository = this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SurfaceRepository::s_inCreateSurface = false;
|
bool SurfaceRepository::s_inCreateSurface = false;
|
||||||
|
@ -57,8 +57,7 @@ namespace D3dDdi
|
|||||||
CompatWeakPtr<IDirectDrawSurface7> getWindowedPrimary();
|
CompatWeakPtr<IDirectDrawSurface7> getWindowedPrimary();
|
||||||
CompatPtr<IDirectDrawSurface7> getWindowedSrc(RECT rect);
|
CompatPtr<IDirectDrawSurface7> getWindowedSrc(RECT rect);
|
||||||
void release(Surface& surface);
|
void release(Surface& surface);
|
||||||
void setAsPrimaryRepo();
|
void setRepository(CompatWeakPtr<IDirectDraw7> dd);
|
||||||
void setRepository(CompatWeakPtr<IDirectDraw7> dd) { m_dd = dd; }
|
|
||||||
|
|
||||||
static SurfaceRepository& get(const Adapter& adapter);
|
static SurfaceRepository& get(const Adapter& adapter);
|
||||||
static SurfaceRepository& getPrimaryRepo();
|
static SurfaceRepository& getPrimaryRepo();
|
||||||
|
@ -343,7 +343,7 @@ namespace DDraw
|
|||||||
}
|
}
|
||||||
repo.get()->lpVtbl->SetCooperativeLevel(repo, nullptr, DDSCL_NORMAL);
|
repo.get()->lpVtbl->SetCooperativeLevel(repo, nullptr, DDSCL_NORMAL);
|
||||||
it = repositories.insert({ adapterInfo.luid, repo }).first;
|
it = repositories.insert({ adapterInfo.luid, repo }).first;
|
||||||
D3dDdi::Adapter::setRepository(adapterInfo.luid, it->second, !guid);
|
D3dDdi::Adapter::setRepository(adapterInfo.luid, guid, it->second);
|
||||||
repo.detach();
|
repo.detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include <ddraw.h>
|
#include <ddraw.h>
|
||||||
#include <ddrawi.h>
|
#include <ddrawi.h>
|
||||||
@ -12,18 +13,26 @@ namespace DDraw
|
|||||||
{
|
{
|
||||||
namespace DirectDraw
|
namespace DirectDraw
|
||||||
{
|
{
|
||||||
|
template <typename TSurface>
|
||||||
|
struct IsDirectDraw : std::false_type {};
|
||||||
|
|
||||||
|
template <> struct IsDirectDraw<IDirectDraw> : std::true_type {};
|
||||||
|
template <> struct IsDirectDraw<IDirectDraw2> : std::true_type {};
|
||||||
|
template <> struct IsDirectDraw<IDirectDraw4> : std::true_type {};
|
||||||
|
template <> struct IsDirectDraw<IDirectDraw7> : std::true_type {};
|
||||||
|
|
||||||
DDPIXELFORMAT getRgbPixelFormat(DWORD bpp);
|
DDPIXELFORMAT getRgbPixelFormat(DWORD bpp);
|
||||||
void hookDDrawWindowProc(WNDPROC ddrawWndProc);
|
void hookDDrawWindowProc(WNDPROC ddrawWndProc);
|
||||||
void onCreate(GUID* guid, CompatRef<IDirectDraw7> dd);
|
void onCreate(GUID* guid, CompatRef<IDirectDraw7> dd);
|
||||||
void suppressEmulatedDirectDraw(GUID*& guid);
|
void suppressEmulatedDirectDraw(GUID*& guid);
|
||||||
|
|
||||||
template <typename TDirectDraw>
|
template <typename TDirectDraw, typename = std::enable_if_t<IsDirectDraw<TDirectDraw>::value>>
|
||||||
DDRAWI_DIRECTDRAW_INT& getInt(TDirectDraw& dd)
|
DDRAWI_DIRECTDRAW_INT& getInt(TDirectDraw& dd)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<DDRAWI_DIRECTDRAW_INT&>(dd);
|
return reinterpret_cast<DDRAWI_DIRECTDRAW_INT&>(dd);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TDirectDraw>
|
template <typename TDirectDraw, typename = std::enable_if_t<IsDirectDraw<TDirectDraw>::value>>
|
||||||
HWND* getDeviceWindowPtr(TDirectDraw& dd)
|
HWND* getDeviceWindowPtr(TDirectDraw& dd)
|
||||||
{
|
{
|
||||||
return &reinterpret_cast<HWND>(getInt(dd).lpLcl->hWnd);
|
return &reinterpret_cast<HWND>(getInt(dd).lpLcl->hWnd);
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <DDraw/Surfaces/Surface.h>
|
#include <DDraw/Surfaces/Surface.h>
|
||||||
#include <DDraw/Surfaces/SurfaceImpl.h>
|
#include <DDraw/Surfaces/SurfaceImpl.h>
|
||||||
#include <DDraw/Visitors/DirectDrawSurfaceVtblVisitor.h>
|
#include <DDraw/Visitors/DirectDrawSurfaceVtblVisitor.h>
|
||||||
|
#include <D3dDdi/Device.h>
|
||||||
|
#include <D3dDdi/SurfaceRepository.h>
|
||||||
|
|
||||||
#define SET_COMPAT_METHOD(method) \
|
#define SET_COMPAT_METHOD(method) \
|
||||||
vtable.method = &callImpl<decltype(&DDraw::SurfaceImpl<TSurface>::method), &DDraw::SurfaceImpl<TSurface>::method, \
|
vtable.method = &callImpl<decltype(&DDraw::SurfaceImpl<TSurface>::method), &DDraw::SurfaceImpl<TSurface>::method, \
|
||||||
@ -92,6 +94,12 @@ namespace DDraw
|
|||||||
return context.surfaces;
|
return context.surfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3dDdi::SurfaceRepository* getSurfaceRepository(HANDLE resource)
|
||||||
|
{
|
||||||
|
auto device = D3dDdi::Device::findDeviceByResource(resource);
|
||||||
|
return device ? &device->getRepo() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Vtable>
|
template <typename Vtable>
|
||||||
void hookVtable(const Vtable& vtable)
|
void hookVtable(const Vtable& vtable)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
@ -8,36 +9,58 @@
|
|||||||
#include <Common/CompatPtr.h>
|
#include <Common/CompatPtr.h>
|
||||||
#include <Common/CompatRef.h>
|
#include <Common/CompatRef.h>
|
||||||
|
|
||||||
|
namespace D3dDdi
|
||||||
|
{
|
||||||
|
class SurfaceRepository;
|
||||||
|
}
|
||||||
|
|
||||||
namespace DDraw
|
namespace DDraw
|
||||||
{
|
{
|
||||||
namespace DirectDrawSurface
|
namespace DirectDrawSurface
|
||||||
{
|
{
|
||||||
|
template <typename TSurface>
|
||||||
|
struct IsSurface : std::false_type {};
|
||||||
|
|
||||||
|
template <> struct IsSurface<IDirectDrawSurface> : std::true_type {};
|
||||||
|
template <> struct IsSurface<IDirectDrawSurface2> : std::true_type {};
|
||||||
|
template <> struct IsSurface<IDirectDrawSurface3> : std::true_type {};
|
||||||
|
template <> struct IsSurface<IDirectDrawSurface4> : std::true_type {};
|
||||||
|
template <> struct IsSurface<IDirectDrawSurface7> : std::true_type {};
|
||||||
|
|
||||||
std::vector<CompatPtr<IDirectDrawSurface7>> getAllAttachedSurfaces(CompatRef<IDirectDrawSurface7> surface);
|
std::vector<CompatPtr<IDirectDrawSurface7>> getAllAttachedSurfaces(CompatRef<IDirectDrawSurface7> surface);
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface, typename = std::enable_if_t<IsSurface<TSurface>::value>>
|
||||||
DDRAWI_DDRAWSURFACE_INT& getInt(TSurface& surface)
|
DDRAWI_DDRAWSURFACE_INT& getInt(TSurface& surface)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<DDRAWI_DDRAWSURFACE_INT&>(surface);
|
return reinterpret_cast<DDRAWI_DDRAWSURFACE_INT&>(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface, typename = std::enable_if_t<IsSurface<TSurface>::value>>
|
||||||
HANDLE getRuntimeResourceHandle(TSurface& surface)
|
HANDLE getRuntimeResourceHandle(TSurface& surface)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<HANDLE>(getInt(surface).lpLcl->hDDSurface);
|
return reinterpret_cast<HANDLE>(getInt(surface).lpLcl->hDDSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface, typename = std::enable_if_t<IsSurface<TSurface>::value>>
|
||||||
HANDLE getDriverResourceHandle(TSurface& surface)
|
HANDLE& getDriverResourceHandle(TSurface& surface)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<HANDLE*>(getRuntimeResourceHandle(surface))[0];
|
return reinterpret_cast<HANDLE*>(getRuntimeResourceHandle(surface))[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TSurface>
|
template <typename TSurface, typename = std::enable_if_t<IsSurface<TSurface>::value>>
|
||||||
UINT getSubResourceIndex(TSurface& surface)
|
UINT& getSubResourceIndex(TSurface& surface)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<UINT*>(getRuntimeResourceHandle(surface))[1];
|
return reinterpret_cast<UINT*>(getRuntimeResourceHandle(surface))[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
D3dDdi::SurfaceRepository* getSurfaceRepository(HANDLE resource);
|
||||||
|
|
||||||
|
template <typename TSurface, typename = std::enable_if_t<IsSurface<TSurface>::value>>
|
||||||
|
D3dDdi::SurfaceRepository* getSurfaceRepository(TSurface& surface)
|
||||||
|
{
|
||||||
|
return getSurfaceRepository(getDriverResourceHandle(surface));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Vtable>
|
template <typename Vtable>
|
||||||
void hookVtable(const Vtable& vtable);
|
void hookVtable(const Vtable& vtable);
|
||||||
}
|
}
|
||||||
|
@ -97,9 +97,6 @@ namespace DDraw
|
|||||||
{
|
{
|
||||||
void installHooks(CompatPtr<IDirectDraw7> dd7)
|
void installHooks(CompatPtr<IDirectDraw7> dd7)
|
||||||
{
|
{
|
||||||
DDraw::DirectDraw::onCreate(nullptr, *dd7);
|
|
||||||
RealPrimarySurface::init();
|
|
||||||
|
|
||||||
g_origInitialize = dd7.get()->lpVtbl->Initialize;
|
g_origInitialize = dd7.get()->lpVtbl->Initialize;
|
||||||
Compat::hookFunction(reinterpret_cast<void*&>(g_origInitialize), initialize, "IDirectDrawVtbl::Initialize");
|
Compat::hookFunction(reinterpret_cast<void*&>(g_origInitialize), initialize, "IDirectDrawVtbl::Initialize");
|
||||||
|
|
||||||
@ -107,5 +104,8 @@ namespace DDraw
|
|||||||
hookDirectDrawClipper(*dd7);
|
hookDirectDrawClipper(*dd7);
|
||||||
hookDirectDrawPalette(*dd7);
|
hookDirectDrawPalette(*dd7);
|
||||||
hookDirectDrawSurface(*dd7);
|
hookDirectDrawSurface(*dd7);
|
||||||
|
|
||||||
|
DDraw::DirectDraw::onCreate(nullptr, *dd7);
|
||||||
|
DDraw::RealPrimarySurface::init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include <Gdi/WinProc.h>
|
#include <Gdi/WinProc.h>
|
||||||
#include <Overlay/ConfigWindow.h>
|
#include <Overlay/ConfigWindow.h>
|
||||||
#include <Overlay/StatsWindow.h>
|
#include <Overlay/StatsWindow.h>
|
||||||
|
#include <Overlay/Steam.h>
|
||||||
#include <Win32/DisplayMode.h>
|
#include <Win32/DisplayMode.h>
|
||||||
#include <Win32/DpiAwareness.h>
|
#include <Win32/DpiAwareness.h>
|
||||||
#include <Win32/Thread.h>
|
#include <Win32/Thread.h>
|
||||||
@ -276,18 +277,7 @@ namespace
|
|||||||
D3dDdi::SurfaceRepository* repo = nullptr;
|
D3dDdi::SurfaceRepository* repo = nullptr;
|
||||||
if (src)
|
if (src)
|
||||||
{
|
{
|
||||||
auto resource = DDraw::DirectDrawSurface::getDriverResourceHandle(*frontBuffer);
|
repo = DDraw::DirectDrawSurface::getSurfaceRepository(*frontBuffer);
|
||||||
if (!resource)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto device = D3dDdi::Device::findDeviceByResource(resource);
|
|
||||||
if (!device)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
repo = &device->getRepo();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -364,7 +354,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
Gdi::Cursor::setMonitorClipRect(clipRect);
|
Gdi::Cursor::setMonitorClipRect(clipRect);
|
||||||
Gdi::Cursor::setEmulated(true);
|
Gdi::Cursor::setEmulated(!Overlay::Steam::isOverlayOpen());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,6 +558,7 @@ namespace DDraw
|
|||||||
static UINT lastOverlayCheckVsyncCount = 0;
|
static UINT lastOverlayCheckVsyncCount = 0;
|
||||||
if (vsyncCount != lastOverlayCheckVsyncCount)
|
if (vsyncCount != lastOverlayCheckVsyncCount)
|
||||||
{
|
{
|
||||||
|
updatePresentationParams();
|
||||||
setPresentationWindowTopmost();
|
setPresentationWindowTopmost();
|
||||||
Gdi::Cursor::update();
|
Gdi::Cursor::update();
|
||||||
Gdi::Caret::blink();
|
Gdi::Caret::blink();
|
||||||
@ -577,11 +568,10 @@ namespace DDraw
|
|||||||
statsWindow->updateStats();
|
statsWindow->updateStats();
|
||||||
g_qpcLastUpdate = Time::queryPerformanceCounter();
|
g_qpcLastUpdate = Time::queryPerformanceCounter();
|
||||||
}
|
}
|
||||||
|
Overlay::Steam::flush();
|
||||||
lastOverlayCheckVsyncCount = vsyncCount;
|
lastOverlayCheckVsyncCount = vsyncCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePresentationParams();
|
|
||||||
|
|
||||||
bool isOverlayOnly = false;
|
bool isOverlayOnly = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -325,6 +325,7 @@
|
|||||||
<ClInclude Include="Overlay\StatsEventRate.h" />
|
<ClInclude Include="Overlay\StatsEventRate.h" />
|
||||||
<ClInclude Include="Overlay\StatsTimer.h" />
|
<ClInclude Include="Overlay\StatsTimer.h" />
|
||||||
<ClInclude Include="Overlay\StatsWindow.h" />
|
<ClInclude Include="Overlay\StatsWindow.h" />
|
||||||
|
<ClInclude Include="Overlay\Steam.h" />
|
||||||
<ClInclude Include="Overlay\Window.h" />
|
<ClInclude Include="Overlay\Window.h" />
|
||||||
<ClInclude Include="Win32\DisplayMode.h" />
|
<ClInclude Include="Win32\DisplayMode.h" />
|
||||||
<ClInclude Include="Win32\DpiAwareness.h" />
|
<ClInclude Include="Win32\DpiAwareness.h" />
|
||||||
@ -459,6 +460,7 @@
|
|||||||
<ClCompile Include="Overlay\StatsEventRate.cpp" />
|
<ClCompile Include="Overlay\StatsEventRate.cpp" />
|
||||||
<ClCompile Include="Overlay\StatsTimer.cpp" />
|
<ClCompile Include="Overlay\StatsTimer.cpp" />
|
||||||
<ClCompile Include="Overlay\StatsWindow.cpp" />
|
<ClCompile Include="Overlay\StatsWindow.cpp" />
|
||||||
|
<ClCompile Include="Overlay\Steam.cpp" />
|
||||||
<ClCompile Include="Overlay\Window.cpp" />
|
<ClCompile Include="Overlay\Window.cpp" />
|
||||||
<ClCompile Include="Win32\DisplayMode.cpp" />
|
<ClCompile Include="Win32\DisplayMode.cpp" />
|
||||||
<ClCompile Include="Win32\DpiAwareness.cpp" />
|
<ClCompile Include="Win32\DpiAwareness.cpp" />
|
||||||
|
@ -708,6 +708,9 @@
|
|||||||
<ClInclude Include="Win32\DpiAwareness.h">
|
<ClInclude Include="Win32\DpiAwareness.h">
|
||||||
<Filter>Header Files\Win32</Filter>
|
<Filter>Header Files\Win32</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Overlay\Steam.h">
|
||||||
|
<Filter>Header Files\Overlay</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="Gdi\Gdi.cpp">
|
<ClCompile Include="Gdi\Gdi.cpp">
|
||||||
@ -1106,6 +1109,9 @@
|
|||||||
<ClCompile Include="Win32\DpiAwareness.cpp">
|
<ClCompile Include="Win32\DpiAwareness.cpp">
|
||||||
<Filter>Source Files\Win32</Filter>
|
<Filter>Source Files\Win32</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Overlay\Steam.cpp">
|
||||||
|
<Filter>Source Files\Overlay</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="DDrawCompat.rc">
|
<ResourceCompile Include="DDrawCompat.rc">
|
||||||
|
@ -10,6 +10,7 @@ namespace Dll
|
|||||||
HMODULE g_origDciman32Module = nullptr;
|
HMODULE g_origDciman32Module = nullptr;
|
||||||
Procs g_origProcs = {};
|
Procs g_origProcs = {};
|
||||||
Procs g_jmpTargetProcs = {};
|
Procs g_jmpTargetProcs = {};
|
||||||
|
Procs g_newProcs = {};
|
||||||
bool g_isHooked = false;
|
bool g_isHooked = false;
|
||||||
|
|
||||||
HANDLE createThread(unsigned(__stdcall* threadProc)(void*), unsigned int* threadId, int priority, unsigned initFlags)
|
HANDLE createThread(unsigned(__stdcall* threadProc)(void*), unsigned int* threadId, int priority, unsigned initFlags)
|
||||||
|
@ -80,6 +80,7 @@ namespace Dll
|
|||||||
extern HMODULE g_origDciman32Module;
|
extern HMODULE g_origDciman32Module;
|
||||||
extern Procs g_origProcs;
|
extern Procs g_origProcs;
|
||||||
extern Procs g_jmpTargetProcs;
|
extern Procs g_jmpTargetProcs;
|
||||||
|
extern Procs g_newProcs;
|
||||||
extern bool g_isHooked;
|
extern bool g_isHooked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Gdi/VirtualScreen.h>
|
#include <Gdi/VirtualScreen.h>
|
||||||
#include <Input/Input.h>
|
#include <Input/Input.h>
|
||||||
|
#include <Overlay/Steam.h>
|
||||||
#include <Win32/DisplayMode.h>
|
#include <Win32/DisplayMode.h>
|
||||||
#include <Win32/DpiAwareness.h>
|
#include <Win32/DpiAwareness.h>
|
||||||
#include <Win32/MemoryManagement.h>
|
#include <Win32/MemoryManagement.h>
|
||||||
@ -82,7 +83,9 @@ namespace
|
|||||||
{
|
{
|
||||||
if (!Dll::g_isHooked)
|
if (!Dll::g_isHooked)
|
||||||
{
|
{
|
||||||
|
Dll::g_isHooked = true;
|
||||||
DDraw::SuppressResourceFormatLogs suppressResourceFormatLogs;
|
DDraw::SuppressResourceFormatLogs suppressResourceFormatLogs;
|
||||||
|
Overlay::Steam::installHooks();
|
||||||
LOG_INFO << "Installing display mode hooks";
|
LOG_INFO << "Installing display mode hooks";
|
||||||
Win32::DisplayMode::installHooks();
|
Win32::DisplayMode::installHooks();
|
||||||
LOG_INFO << "Installing registry hooks";
|
LOG_INFO << "Installing registry hooks";
|
||||||
@ -129,7 +132,6 @@ namespace
|
|||||||
Gdi::installHooks();
|
Gdi::installHooks();
|
||||||
Compat::closeDbgEng();
|
Compat::closeDbgEng();
|
||||||
LOG_INFO << "Finished installing hooks";
|
LOG_INFO << "Finished installing hooks";
|
||||||
Dll::g_isHooked = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +246,8 @@ namespace
|
|||||||
Dll::g_origProcs.proc = Compat::getProcAddress(origModule, #proc);
|
Dll::g_origProcs.proc = Compat::getProcAddress(origModule, #proc);
|
||||||
|
|
||||||
#define HOOK_DDRAW_PROC(proc) \
|
#define HOOK_DDRAW_PROC(proc) \
|
||||||
|
Dll::g_newProcs.proc = reinterpret_cast<FARPROC>( \
|
||||||
|
static_cast<decltype(&proc)>(&directDrawFunc<&Dll::Procs::proc, decltype(&proc)>)); \
|
||||||
Compat::hookFunction( \
|
Compat::hookFunction( \
|
||||||
reinterpret_cast<void*&>(Dll::g_origProcs.proc), \
|
reinterpret_cast<void*&>(Dll::g_origProcs.proc), \
|
||||||
static_cast<decltype(&proc)>(&directDrawFunc<&Dll::Procs::proc, decltype(&proc)>), \
|
static_cast<decltype(&proc)>(&directDrawFunc<&Dll::Procs::proc, decltype(&proc)>), \
|
||||||
@ -302,7 +306,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dll::g_origDDrawModule = LoadLibraryW((systemPath / "ddraw.dll").c_str());
|
auto origDDrawModulePath = systemPath / "ddraw.dll";
|
||||||
|
Dll::g_origDDrawModule = LoadLibraryW(origDDrawModulePath.c_str());
|
||||||
if (!Dll::g_origDDrawModule)
|
if (!Dll::g_origDDrawModule)
|
||||||
{
|
{
|
||||||
LOG_INFO << "ERROR: Failed to load system ddraw.dll from " << systemPath.u8string();
|
LOG_INFO << "ERROR: Failed to load system ddraw.dll from " << systemPath.u8string();
|
||||||
@ -323,6 +328,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Dll::g_jmpTargetProcs = Dll::g_origProcs;
|
Dll::g_jmpTargetProcs = Dll::g_origProcs;
|
||||||
|
Overlay::Steam::init(origDDrawModulePath.c_str());
|
||||||
|
|
||||||
VISIT_PUBLIC_DDRAW_PROCS(HOOK_DDRAW_PROC);
|
VISIT_PUBLIC_DDRAW_PROCS(HOOK_DDRAW_PROC);
|
||||||
Compat::hookFunction(reinterpret_cast<void*&>(Dll::g_origProcs.SetAppCompatData),
|
Compat::hookFunction(reinterpret_cast<void*&>(Dll::g_origProcs.SetAppCompatData),
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <Gdi/WinProc.h>
|
#include <Gdi/WinProc.h>
|
||||||
#include <Overlay/ConfigWindow.h>
|
#include <Overlay/ConfigWindow.h>
|
||||||
#include <Overlay/StatsWindow.h>
|
#include <Overlay/StatsWindow.h>
|
||||||
|
#include <Overlay/Steam.h>
|
||||||
#include <Win32/DisplayMode.h>
|
#include <Win32/DisplayMode.h>
|
||||||
#include <Win32/DpiAwareness.h>
|
#include <Win32/DpiAwareness.h>
|
||||||
|
|
||||||
@ -178,16 +179,13 @@ namespace
|
|||||||
|
|
||||||
LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
LOG_FUNC("messageWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
|
|
||||||
|
|
||||||
if (WM_USER_EXECUTE == uMsg)
|
if (WM_USER_EXECUTE == uMsg)
|
||||||
{
|
{
|
||||||
auto& func = *reinterpret_cast<const std::function<void()>*>(lParam);
|
auto& func = *reinterpret_cast<const std::function<void()>*>(lParam);
|
||||||
func();
|
func();
|
||||||
return LOG_RESULT(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
|
||||||
return LOG_RESULT(CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned WINAPI messageWindowThreadProc(LPVOID /*lpParameter*/)
|
unsigned WINAPI messageWindowThreadProc(LPVOID /*lpParameter*/)
|
||||||
@ -230,7 +228,6 @@ namespace
|
|||||||
MSG msg = {};
|
MSG msg = {};
|
||||||
while (CALL_ORIG_FUNC(GetMessageA)(&msg, nullptr, 0, 0))
|
while (CALL_ORIG_FUNC(GetMessageA)(&msg, nullptr, 0, 0))
|
||||||
{
|
{
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,6 +273,7 @@ namespace Gdi
|
|||||||
|
|
||||||
void destroyWindow(HWND hwnd)
|
void destroyWindow(HWND hwnd)
|
||||||
{
|
{
|
||||||
|
Overlay::Steam::onDestroyWindow(hwnd);
|
||||||
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
PostMessage(hwnd, WM_CLOSE, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ namespace
|
|||||||
LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
|
LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
|
||||||
return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
|
return LOG_RESULT(CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ namespace Gdi
|
|||||||
GuiThread::execute([&]()
|
GuiThread::execute([&]()
|
||||||
{
|
{
|
||||||
presentationWindow = GuiThread::createWindow(
|
presentationWindow = GuiThread::createWindow(
|
||||||
WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY | (owner ? 0 : WS_EX_TOOLWINDOW),
|
WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY | WS_EX_NOACTIVATE | (owner ? 0 : WS_EX_TOOLWINDOW),
|
||||||
reinterpret_cast<const wchar_t*>(g_classAtom),
|
reinterpret_cast<const wchar_t*>(g_classAtom),
|
||||||
nullptr,
|
nullptr,
|
||||||
WS_DISABLED | WS_POPUP,
|
WS_DISABLED | WS_POPUP,
|
||||||
@ -56,6 +56,7 @@ namespace Gdi
|
|||||||
WNDCLASS wc = {};
|
WNDCLASS wc = {};
|
||||||
wc.lpfnWndProc = &presentationWindowProc;
|
wc.lpfnWndProc = &presentationWindowProc;
|
||||||
wc.hInstance = Dll::g_currentModule;
|
wc.hInstance = Dll::g_currentModule;
|
||||||
|
wc.hCursor = CALL_ORIG_FUNC(LoadCursorA)(nullptr, IDC_ARROW);
|
||||||
wc.lpszClassName = "DDrawCompatPresentationWindow";
|
wc.lpszClassName = "DDrawCompatPresentationWindow";
|
||||||
g_classAtom = CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
g_classAtom = CALL_ORIG_FUNC(RegisterClassA)(&wc);
|
||||||
}
|
}
|
||||||
|
@ -206,22 +206,22 @@ namespace
|
|||||||
{
|
{
|
||||||
case HTLEFT:
|
case HTLEFT:
|
||||||
case HTRIGHT:
|
case HTRIGHT:
|
||||||
SetCursor(LoadCursor(nullptr, IDC_SIZEWE));
|
SetCursor(CALL_ORIG_FUNC(LoadCursorA)(nullptr, IDC_SIZEWE));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case HTTOP:
|
case HTTOP:
|
||||||
case HTBOTTOM:
|
case HTBOTTOM:
|
||||||
SetCursor(LoadCursor(nullptr, IDC_SIZENS));
|
SetCursor(CALL_ORIG_FUNC(LoadCursorA)(nullptr, IDC_SIZENS));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case HTTOPLEFT:
|
case HTTOPLEFT:
|
||||||
case HTBOTTOMRIGHT:
|
case HTBOTTOMRIGHT:
|
||||||
SetCursor(LoadCursor(nullptr, IDC_SIZENWSE));
|
SetCursor(CALL_ORIG_FUNC(LoadCursorA)(nullptr, IDC_SIZENWSE));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case HTBOTTOMLEFT:
|
case HTBOTTOMLEFT:
|
||||||
case HTTOPRIGHT:
|
case HTTOPRIGHT:
|
||||||
SetCursor(LoadCursor(nullptr, IDC_SIZENESW));
|
SetCursor(CALL_ORIG_FUNC(LoadCursorA)(nullptr, IDC_SIZENESW));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ namespace
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetCursor(LoadCursor(nullptr, IDC_ARROW));
|
SetCursor(CALL_ORIG_FUNC(LoadCursorA)(nullptr, IDC_ARROW));
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -530,7 +530,7 @@ namespace
|
|||||||
case WM_SETCURSOR:
|
case WM_SETCURSOR:
|
||||||
if (CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_STYLE) & (SBS_SIZEBOX | SBS_SIZEGRIP))
|
if (CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_STYLE) & (SBS_SIZEBOX | SBS_SIZEGRIP))
|
||||||
{
|
{
|
||||||
SetCursor(LoadCursor(nullptr, IDC_SIZENWSE));
|
SetCursor(CALL_ORIG_FUNC(LoadCursorA)(nullptr, IDC_SIZENWSE));
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -153,19 +153,13 @@ namespace Gdi
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto resource = DDraw::DirectDrawSurface::getDriverResourceHandle(*primary);
|
auto repo = DDraw::DirectDrawSurface::getSurfaceRepository(*DDraw::PrimarySurface::getPrimary());
|
||||||
if (!resource)
|
if (!repo)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto device = D3dDdi::Device::findDeviceByResource(resource);
|
auto dd(repo->getDirectDraw());
|
||||||
if (!device)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dd(device->getRepo().getDirectDraw());
|
|
||||||
if (!dd)
|
if (!dd)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <Gdi/PresentationWindow.h>
|
#include <Gdi/PresentationWindow.h>
|
||||||
#include <Input/Input.h>
|
#include <Input/Input.h>
|
||||||
#include <Overlay/ConfigWindow.h>
|
#include <Overlay/ConfigWindow.h>
|
||||||
|
#include <Overlay/Steam.h>
|
||||||
#include <Overlay/Window.h>
|
#include <Overlay/Window.h>
|
||||||
#include <Win32/DisplayMode.h>
|
#include <Win32/DisplayMode.h>
|
||||||
|
|
||||||
@ -157,6 +158,12 @@ namespace
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto steamWindow = Overlay::Steam::getWindow();
|
||||||
|
if (steamWindow)
|
||||||
|
{
|
||||||
|
PostMessage(steamWindow, wParam, llHook->vkCode, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CallNextHookEx(nullptr, nCode, wParam, lParam);
|
return CallNextHookEx(nullptr, nCode, wParam, lParam);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <Overlay/ConfigWindow.h>
|
#include <Overlay/ConfigWindow.h>
|
||||||
#include <Overlay/SettingControl.h>
|
#include <Overlay/SettingControl.h>
|
||||||
#include <Overlay/StatsWindow.h>
|
#include <Overlay/StatsWindow.h>
|
||||||
|
#include <Overlay/Steam.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -275,6 +276,11 @@ namespace Overlay
|
|||||||
{
|
{
|
||||||
if (isVisible != Window::isVisible())
|
if (isVisible != Window::isVisible())
|
||||||
{
|
{
|
||||||
|
if (isVisible && Overlay::Steam::isOverlayOpen())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Window::setVisible(isVisible);
|
Window::setVisible(isVisible);
|
||||||
Input::setCapture(isVisible ? this : nullptr);
|
Input::setCapture(isVisible ? this : nullptr);
|
||||||
setFocus(nullptr);
|
setFocus(nullptr);
|
||||||
|
395
DDrawCompat/Overlay/Steam.cpp
Normal file
395
DDrawCompat/Overlay/Steam.cpp
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
#include <Common/Hook.h>
|
||||||
|
#include <Common/Log.h>
|
||||||
|
#include <Common/Time.h>
|
||||||
|
#include <D3dDdi/Adapter.h>
|
||||||
|
#include <D3dDdi/Device.h>
|
||||||
|
#include <D3dDdi/Resource.h>
|
||||||
|
#include <Dll/Dll.h>
|
||||||
|
#include <DDraw/DirectDrawSurface.h>
|
||||||
|
#include <DDraw/RealPrimarySurface.h>
|
||||||
|
#include <Gdi/Cursor.h>
|
||||||
|
#include <Gdi/GuiThread.h>
|
||||||
|
#include <Overlay/ConfigWindow.h>
|
||||||
|
#include <Overlay/Steam.h>
|
||||||
|
#include <Win32/DpiAwareness.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
decltype(&DirectDrawCreateEx) g_steamDirectDrawCreateEx = nullptr;
|
||||||
|
D3dDdi::Adapter* g_adapter = nullptr;
|
||||||
|
IDirectDraw7* g_dd = nullptr;
|
||||||
|
IDirect3D7* g_d3d = nullptr;
|
||||||
|
IDirectDrawSurface7* g_rt = nullptr;
|
||||||
|
D3dDdi::Resource* g_rtResource = nullptr;
|
||||||
|
D3dDdi::Resource* g_bbResource = nullptr;
|
||||||
|
UINT g_bbSubResourceIndex = 0;
|
||||||
|
IDirect3DDevice7* g_dev = nullptr;
|
||||||
|
UINT g_width = 0;
|
||||||
|
UINT g_height = 0;
|
||||||
|
bool g_isOverlayOpen = false;
|
||||||
|
long long g_qpcLastRender = 0;
|
||||||
|
HWND g_window = nullptr;
|
||||||
|
|
||||||
|
void releaseDevice();
|
||||||
|
void* getTargetFunc(void* hookedFunc);
|
||||||
|
|
||||||
|
BOOL WINAPI flushInstructionCache(HANDLE hProcess, LPCVOID lpBaseAddress, SIZE_T dwSize)
|
||||||
|
{
|
||||||
|
LOG_FUNC("FlushInstructionCache", hProcess, lpBaseAddress, dwSize);
|
||||||
|
auto hookedFunc = const_cast<BYTE*>(static_cast<const BYTE*>(lpBaseAddress));
|
||||||
|
if ((Dll::g_jmpTargetProcs.DirectDrawCreate == lpBaseAddress ||
|
||||||
|
Dll::g_jmpTargetProcs.DirectDrawCreateEx == lpBaseAddress) &&
|
||||||
|
0xE9 == hookedFunc[0] && 5 == dwSize)
|
||||||
|
{
|
||||||
|
int& jmpOffset = *reinterpret_cast<int*>(hookedFunc + 1);
|
||||||
|
decltype(&DirectDrawCreateEx) directDrawCreateEx = nullptr;
|
||||||
|
if (!g_steamDirectDrawCreateEx && Dll::g_jmpTargetProcs.DirectDrawCreateEx == lpBaseAddress)
|
||||||
|
{
|
||||||
|
directDrawCreateEx = reinterpret_cast<decltype(&DirectDrawCreateEx)>(hookedFunc + 5 + jmpOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto targetFunc = getTargetFunc(hookedFunc);
|
||||||
|
auto gameOverlayRenderer = GetModuleHandle("GameOverlayRenderer.dll");
|
||||||
|
if (gameOverlayRenderer && Compat::getModuleHandleFromAddress(targetFunc) == gameOverlayRenderer)
|
||||||
|
{
|
||||||
|
if (directDrawCreateEx)
|
||||||
|
{
|
||||||
|
g_steamDirectDrawCreateEx = directDrawCreateEx;
|
||||||
|
LOG_INFO << "Steam overlay support activated";
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG << "Restoring hook: " << Compat::funcPtrToStr(lpBaseAddress);
|
||||||
|
DWORD oldProtect = 0;
|
||||||
|
VirtualProtect(hookedFunc, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||||
|
auto newFunc = Dll::g_jmpTargetProcs.DirectDrawCreate == lpBaseAddress
|
||||||
|
? Dll::g_newProcs.DirectDrawCreate : Dll::g_newProcs.DirectDrawCreateEx;
|
||||||
|
jmpOffset = reinterpret_cast<BYTE*>(newFunc) - (hookedFunc + 5);
|
||||||
|
VirtualProtect(hookedFunc, 5, PAGE_EXECUTE_READ, &oldProtect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LOG_RESULT(CALL_ORIG_FUNC(FlushInstructionCache)(hProcess, lpBaseAddress, dwSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND WINAPI getActiveWindow()
|
||||||
|
{
|
||||||
|
LOG_FUNC("steamGetActiveWindow");
|
||||||
|
return LOG_RESULT(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI getClientRect(HWND hWnd, LPRECT lpRect)
|
||||||
|
{
|
||||||
|
LOG_FUNC("steamGetClientRect", hWnd, lpRect);
|
||||||
|
Win32::ScopedDpiAwareness dpiAwareness;
|
||||||
|
return LOG_RESULT(GetClientRect(hWnd, lpRect));
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND WINAPI getForegroundWindow()
|
||||||
|
{
|
||||||
|
LOG_FUNC("steamGetForegroundWindow");
|
||||||
|
HWND result = GetForegroundWindow();
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
HWND presentationWindow = DDraw::RealPrimarySurface::getPresentationWindow();
|
||||||
|
if (presentationWindow && GetParent(presentationWindow) == result)
|
||||||
|
{
|
||||||
|
g_window = presentationWindow;
|
||||||
|
return LOG_RESULT(presentationWindow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LOG_RESULT(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* getTargetFunc(void* hookedFunc)
|
||||||
|
{
|
||||||
|
auto targetFunc = reinterpret_cast<BYTE*>(hookedFunc);
|
||||||
|
while (0xE9 == targetFunc[0])
|
||||||
|
{
|
||||||
|
targetFunc += 5 + *reinterpret_cast<int*>(targetFunc + 1);
|
||||||
|
}
|
||||||
|
return targetFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Intf>
|
||||||
|
void release(Intf*& intf)
|
||||||
|
{
|
||||||
|
if (intf)
|
||||||
|
{
|
||||||
|
intf->lpVtbl->Release(intf);
|
||||||
|
intf = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseAll()
|
||||||
|
{
|
||||||
|
releaseDevice();
|
||||||
|
release(g_d3d);
|
||||||
|
release(g_dd);
|
||||||
|
g_adapter = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseDevice()
|
||||||
|
{
|
||||||
|
release(g_dev);
|
||||||
|
release(g_rt);
|
||||||
|
g_rtResource = nullptr;
|
||||||
|
g_width = 0;
|
||||||
|
g_height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* removeHook(HMODULE gameOverlayRenderer, const wchar_t* origDDrawModulePath, void* hookedFunc)
|
||||||
|
{
|
||||||
|
LOG_FUNC("Steam::removeHook", gameOverlayRenderer, origDDrawModulePath, hookedFunc);
|
||||||
|
auto targetFunc = getTargetFunc(hookedFunc);
|
||||||
|
if (targetFunc != hookedFunc && Compat::getModuleHandleFromAddress(targetFunc) == gameOverlayRenderer)
|
||||||
|
{
|
||||||
|
auto offset = Compat::getModuleFileOffset(hookedFunc);
|
||||||
|
if (0 == offset)
|
||||||
|
{
|
||||||
|
return LOG_RESULT(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream f(origDDrawModulePath, std::ios::in | std::ios::binary);
|
||||||
|
f.seekg(offset);
|
||||||
|
char instructions[20] = {};
|
||||||
|
f.read(instructions, sizeof(instructions));
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
unsigned totalInstructionSize = 0;
|
||||||
|
while (totalInstructionSize < 5)
|
||||||
|
{
|
||||||
|
unsigned instructionSize = Compat::getInstructionSize(instructions + totalInstructionSize);
|
||||||
|
if (0 == instructionSize)
|
||||||
|
{
|
||||||
|
return LOG_RESULT(nullptr);
|
||||||
|
}
|
||||||
|
totalInstructionSize += instructionSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD oldProtect = 0;
|
||||||
|
VirtualProtect(hookedFunc, totalInstructionSize, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||||
|
memcpy(hookedFunc, instructions, totalInstructionSize);
|
||||||
|
VirtualProtect(hookedFunc, totalInstructionSize, PAGE_EXECUTE_READ, &oldProtect);
|
||||||
|
CALL_ORIG_FUNC(FlushInstructionCache)(GetCurrentProcess(), hookedFunc, totalInstructionSize);
|
||||||
|
|
||||||
|
return LOG_RESULT(targetFunc);
|
||||||
|
}
|
||||||
|
return LOG_RESULT(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG WINAPI setClassLongW(HWND hWnd, int nIndex, LONG dwNewLong)
|
||||||
|
{
|
||||||
|
LOG_FUNC("steamSetClassLongW", hWnd, nIndex, dwNewLong);
|
||||||
|
if (GCLP_HCURSOR == nIndex)
|
||||||
|
{
|
||||||
|
HWND presentationWindow = DDraw::RealPrimarySurface::getPresentationWindow();
|
||||||
|
if (presentationWindow && presentationWindow == hWnd)
|
||||||
|
{
|
||||||
|
g_isOverlayOpen = 0 == dwNewLong;
|
||||||
|
LOG_DEBUG << "Steam overlay is " << (g_isOverlayOpen ? "opening" : "closing");
|
||||||
|
|
||||||
|
auto exStyle = CALL_ORIG_FUNC(GetWindowLongA)(hWnd, GWL_EXSTYLE);
|
||||||
|
CALL_ORIG_FUNC(SetWindowLongA)(hWnd, GWL_EXSTYLE,
|
||||||
|
g_isOverlayOpen ? (exStyle & ~WS_EX_TRANSPARENT) : (exStyle | WS_EX_TRANSPARENT));
|
||||||
|
|
||||||
|
if (g_isOverlayOpen)
|
||||||
|
{
|
||||||
|
auto configWindow = Gdi::GuiThread::getConfigWindow();
|
||||||
|
if (configWindow)
|
||||||
|
{
|
||||||
|
configWindow->setVisible(false);
|
||||||
|
}
|
||||||
|
Gdi::Cursor::setEmulated(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LOG_RESULT(CALL_ORIG_FUNC(SetWindowLongW)(hWnd, nIndex, dwNewLong));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool updateDevice(D3dDdi::Resource& resource)
|
||||||
|
{
|
||||||
|
auto adapter = &resource.getDevice().getAdapter();
|
||||||
|
if (adapter != g_adapter)
|
||||||
|
{
|
||||||
|
releaseAll();
|
||||||
|
g_adapter = adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_dd)
|
||||||
|
{
|
||||||
|
auto result = g_steamDirectDrawCreateEx(
|
||||||
|
adapter->getGuid(), reinterpret_cast<void**>(&g_dd), IID_IDirectDraw7, nullptr);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
LOG_ONCE("Failed to create DirectDraw object for Steam overlay: " << Compat::hex(result));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = g_dd->lpVtbl->SetCooperativeLevel(g_dd, nullptr, DDSCL_NORMAL);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
LOG_ONCE("Failed to set cooperative level for Steam overlay: " << Compat::hex(result));
|
||||||
|
release(g_dd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_d3d)
|
||||||
|
{
|
||||||
|
auto result = g_dd->lpVtbl->QueryInterface(g_dd, IID_IDirect3D7, reinterpret_cast<void**>(&g_d3d));
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
LOG_ONCE("Failed to create Direct3D object for Steam overlay: " << Compat::hex(result));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& si = resource.getFixedDesc().pSurfList[0];
|
||||||
|
if (!g_rt || si.Width != g_width || si.Height != g_height || FAILED(g_rt->lpVtbl->IsLost(g_rt)))
|
||||||
|
{
|
||||||
|
releaseDevice();
|
||||||
|
|
||||||
|
DDSURFACEDESC2 desc = {};
|
||||||
|
desc.dwSize = sizeof(desc);
|
||||||
|
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
|
||||||
|
desc.dwWidth = si.Width;
|
||||||
|
desc.dwHeight = si.Height;
|
||||||
|
desc.ddpfPixelFormat = D3dDdi::getPixelFormat(D3DDDIFMT_X8R8G8B8);
|
||||||
|
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY;
|
||||||
|
|
||||||
|
auto& formats = adapter->getInfo().formatOps;
|
||||||
|
if (formats.find(D3dDdi::FOURCC_NULL) != formats.end())
|
||||||
|
{
|
||||||
|
D3dDdi::Resource::setFormatOverride(D3dDdi::FOURCC_NULL);
|
||||||
|
}
|
||||||
|
D3dDdi::Resource::enableConfig(false);
|
||||||
|
auto result = g_dd->lpVtbl->CreateSurface(g_dd, &desc, &g_rt, nullptr);
|
||||||
|
D3dDdi::Resource::enableConfig(true);
|
||||||
|
D3dDdi::Resource::setFormatOverride(D3DDDIFMT_UNKNOWN);
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
LOG_ONCE("Failed to create DirectDrawSurface object for Steam overlay: " << Compat::hex(result));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_width = si.Width;
|
||||||
|
g_height = si.Height;
|
||||||
|
g_rtResource = D3dDdi::Device::findResource(DDraw::DirectDrawSurface::getDriverResourceHandle(*g_rt));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_dev)
|
||||||
|
{
|
||||||
|
auto result = g_d3d->lpVtbl->CreateDevice(g_d3d, IID_IDirect3DHALDevice, g_rt, &g_dev);
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
LOG_ONCE("Failed to create Direct3DDevice for Steam overlay: " << Compat::hex(result));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dev->lpVtbl->BeginScene(g_dev);
|
||||||
|
g_dev->lpVtbl->Clear(g_dev, 0, nullptr, D3DCLEAR_TARGET, 0, 0, 0);
|
||||||
|
g_dev->lpVtbl->EndScene(g_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Overlay
|
||||||
|
{
|
||||||
|
namespace Steam
|
||||||
|
{
|
||||||
|
void flush()
|
||||||
|
{
|
||||||
|
if (!g_steamDirectDrawCreateEx)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto qpcNow = Time::queryPerformanceCounter();
|
||||||
|
if (g_isOverlayOpen || qpcNow - g_qpcLastRender > Time::g_qpcFrequency / 20)
|
||||||
|
{
|
||||||
|
DDraw::RealPrimarySurface::scheduleOverlayUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resources getResources()
|
||||||
|
{
|
||||||
|
Resources resources = {};
|
||||||
|
resources.rtResource = g_rtResource;
|
||||||
|
resources.bbResource = g_bbResource;
|
||||||
|
resources.bbSubResourceIndex = g_bbSubResourceIndex;
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
HWND getWindow()
|
||||||
|
{
|
||||||
|
return g_window;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(const wchar_t* origDDrawModulePath)
|
||||||
|
{
|
||||||
|
HOOK_FUNCTION(kernel32, FlushInstructionCache, flushInstructionCache);
|
||||||
|
|
||||||
|
auto gameOverlayRenderer = GetModuleHandle("GameOverlayRenderer.dll");
|
||||||
|
if (!gameOverlayRenderer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeHook(gameOverlayRenderer, origDDrawModulePath, Dll::g_jmpTargetProcs.DirectDrawCreate);
|
||||||
|
g_steamDirectDrawCreateEx = static_cast<decltype(&DirectDrawCreateEx)>(
|
||||||
|
removeHook(gameOverlayRenderer, origDDrawModulePath, Dll::g_jmpTargetProcs.DirectDrawCreateEx));
|
||||||
|
|
||||||
|
if (g_steamDirectDrawCreateEx)
|
||||||
|
{
|
||||||
|
LOG_INFO << "Steam overlay support activated";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void installHooks()
|
||||||
|
{
|
||||||
|
auto gameOverlayRenderer = GetModuleHandle("GameOverlayRenderer.dll");
|
||||||
|
if (!gameOverlayRenderer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO << "Installing Steam overlay hooks";
|
||||||
|
Compat::hookIatFunction(gameOverlayRenderer, "GetActiveWindow", getActiveWindow);
|
||||||
|
Compat::hookIatFunction(gameOverlayRenderer, "GetClientRect", getClientRect);
|
||||||
|
Compat::hookIatFunction(gameOverlayRenderer, "GetForegroundWindow", getForegroundWindow);
|
||||||
|
Compat::hookIatFunction(gameOverlayRenderer, "SetClassLongW", setClassLongW);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOverlayOpen()
|
||||||
|
{
|
||||||
|
return g_isOverlayOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDestroyWindow(HWND hwnd)
|
||||||
|
{
|
||||||
|
if (hwnd == g_window)
|
||||||
|
{
|
||||||
|
g_window = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render(D3dDdi::Resource& resource, unsigned subResourceIndex)
|
||||||
|
{
|
||||||
|
LOG_FUNC("Steam::render", resource, subResourceIndex);
|
||||||
|
if (!g_steamDirectDrawCreateEx || !updateDevice(resource))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_bbResource = &resource;
|
||||||
|
g_bbSubResourceIndex = subResourceIndex;
|
||||||
|
g_dev->lpVtbl->BeginScene(g_dev);
|
||||||
|
g_dev->lpVtbl->EndScene(g_dev);
|
||||||
|
g_bbResource = nullptr;
|
||||||
|
g_bbSubResourceIndex = 0;
|
||||||
|
g_qpcLastRender = Time::queryPerformanceCounter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
DDrawCompat/Overlay/Steam.h
Normal file
28
DDrawCompat/Overlay/Steam.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace D3dDdi
|
||||||
|
{
|
||||||
|
class Resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Overlay
|
||||||
|
{
|
||||||
|
namespace Steam
|
||||||
|
{
|
||||||
|
struct Resources
|
||||||
|
{
|
||||||
|
D3dDdi::Resource* rtResource;
|
||||||
|
D3dDdi::Resource* bbResource;
|
||||||
|
UINT bbSubResourceIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
void flush();
|
||||||
|
Resources getResources();
|
||||||
|
HWND getWindow();
|
||||||
|
void init(const wchar_t* origDDrawModulePath);
|
||||||
|
void installHooks();
|
||||||
|
bool isOverlayOpen();
|
||||||
|
void onDestroyWindow(HWND hwnd);
|
||||||
|
void render(D3dDdi::Resource& resource, unsigned subResourceIndex);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user