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

Partial workaround for black D3DTA_DIFFUSE color on some drivers when RHW=0

Fixes black screen issues under some circumstances (e.g. underwater) in
Might and Magic 9 (issue #48).
This commit is contained in:
narzoul 2019-08-10 14:02:51 +02:00
parent 7068d282ff
commit bb6092e0bd
17 changed files with 213 additions and 15 deletions

View File

@ -7,7 +7,7 @@
struct _D3DDDI_ADAPTERCALLBACKS;
struct _D3DDDI_ADAPTERFUNCS;
struct _D3DDDI_DEVICEALLBACKS;
struct _D3DDDI_DEVICECALLBACKS;
struct _D3DDDI_DEVICEFUNCS;
template <typename Vtable>
@ -20,7 +20,7 @@ template <>
class ScopedVtableFuncLock<_D3DDDI_ADAPTERFUNCS> : public D3dDdi::ScopedCriticalSection {};
template <>
class ScopedVtableFuncLock<_D3DDDI_DEVICEALLBACKS> : public D3dDdi::ScopedCriticalSection {};
class ScopedVtableFuncLock<_D3DDDI_DEVICECALLBACKS> : public D3dDdi::ScopedCriticalSection {};
template <>
class ScopedVtableFuncLock<_D3DDDI_DEVICEFUNCS> : public D3dDdi::ScopedCriticalSection {};
@ -42,9 +42,7 @@ public:
m_origVtable.*ptr = m_srcVtable.*ptr;
if (m_origVtable.*ptr && s_compatVtable.*ptr)
{
#ifdef DEBUGLOGS
Compat::Log() << "Hooking function: " << FuncNameVisitor<Vtable>::getFuncName<MemberDataPtr, ptr>();
#endif
Compat::LogDebug() << "Hooking function: " << FuncNameVisitor<Vtable>::getFuncName<MemberDataPtr, ptr>();
Compat::hookFunction(reinterpret_cast<void*&>(m_origVtable.*ptr),
getThreadSafeFuncPtr<MemberDataPtr, ptr>(s_compatVtable.*ptr));
}

View File

@ -38,6 +38,8 @@ namespace D3dDdi
, m_adapter(Adapter::get(adapter))
, m_device(device)
, m_sharedPrimary(nullptr)
, m_streamSourceData{}
, m_streamSource(nullptr)
{
}
@ -135,6 +137,10 @@ namespace D3dDdi
g_gdiResourceHandle = nullptr;
g_gdiResource = nullptr;
}
if (resource == m_streamSource)
{
m_streamSource = nullptr;
}
}
return result;
@ -155,6 +161,11 @@ namespace D3dDdi
HRESULT Device::drawPrimitive(const D3DDDIARG_DRAWPRIMITIVE& data, const UINT* flagBuffer)
{
if (m_streamSource && 0 != m_streamSourceData.Stride)
{
m_streamSource->fixVertexData(m_streamSourceData.Offset + data.VStart * m_streamSourceData.Stride,
data.PrimitiveCount, m_streamSourceData.Stride);
}
prepareForRendering();
return m_origVtable.pfnDrawPrimitive(m_device, &data, flagBuffer);
}
@ -214,6 +225,28 @@ namespace D3dDdi
return m_origVtable.pfnPresent1(m_device, &data);
}
HRESULT Device::setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& data)
{
HRESULT result = m_origVtable.pfnSetStreamSource(m_device, &data);
if (SUCCEEDED(result) && 0 == data.Stream)
{
m_streamSourceData = data;
m_streamSource = getResource(data.hVertexBuffer);
}
return result;
}
HRESULT Device::setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& data, const void* umBuffer)
{
HRESULT result = m_origVtable.pfnSetStreamSourceUm(m_device, &data, umBuffer);
if (SUCCEEDED(result) && 0 == data.Stream)
{
m_streamSourceData = {};
m_streamSource = nullptr;
}
return result;
}
HRESULT Device::texBlt(const D3DDDIARG_TEXBLT& data)
{
prepareForRendering(data.hDstResource, UINT_MAX, false);

View File

@ -36,6 +36,8 @@ namespace D3dDdi
HRESULT openResource(D3DDDIARG_OPENRESOURCE& data);
HRESULT present(const D3DDDIARG_PRESENT& data);
HRESULT present1(D3DDDIARG_PRESENT1& data);
HRESULT setStreamSource(const D3DDDIARG_SETSTREAMSOURCE& data);
HRESULT setStreamSourceUm(const D3DDDIARG_SETSTREAMSOURCEUM& data, const void* umBuffer);
HRESULT texBlt(const D3DDDIARG_TEXBLT& data);
HRESULT texBlt1(const D3DDDIARG_TEXBLT1& data);
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
@ -76,6 +78,8 @@ namespace D3dDdi
std::map<std::pair<HANDLE, UINT>, Resource&> m_dirtyRenderTargets;
std::map<std::pair<HANDLE, UINT>, Resource&> m_dirtyTextures;
HANDLE m_sharedPrimary;
D3DDDIARG_SETSTREAMSOURCE m_streamSourceData;
Resource* m_streamSource;
static std::map<HANDLE, Device> s_devices;
};

View File

@ -54,6 +54,8 @@ namespace D3dDdi
vtable.pfnOpenResource = &DEVICE_FUNC(openResource);
vtable.pfnPresent = &DEVICE_FUNC(present);
vtable.pfnPresent1 = &DEVICE_FUNC(present1);
vtable.pfnSetStreamSource = &DEVICE_FUNC(setStreamSource);
vtable.pfnSetStreamSourceUm = &DEVICE_FUNC(setStreamSourceUm);
vtable.pfnTexBlt = &DEVICE_FUNC(texBlt);
vtable.pfnTexBlt1 = &DEVICE_FUNC(texBlt1);
vtable.pfnUnlock = &DEVICE_FUNC(unlock);

View File

@ -88,6 +88,44 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATERESOURCE2& val)
<< Compat::hex(val.Flags2.Value);
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWINDEXEDPRIMITIVE& val)
{
return Compat::LogStruct(os)
<< val.PrimitiveType
<< val.BaseVertexIndex
<< val.MinIndex
<< val.NumVertices
<< val.StartIndex
<< val.PrimitiveCount;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWINDEXEDPRIMITIVE2& val)
{
return Compat::LogStruct(os)
<< val.PrimitiveType
<< val.BaseVertexOffset
<< val.MinIndex
<< val.NumVertices
<< val.StartIndexOffset
<< val.PrimitiveCount;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWPRIMITIVE& val)
{
return Compat::LogStruct(os)
<< val.PrimitiveType
<< val.VStart
<< val.PrimitiveCount;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWPRIMITIVE2& val)
{
return Compat::LogStruct(os)
<< val.PrimitiveType
<< val.FirstVertexOffset
<< val.PrimitiveCount;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_LOCK& val)
{
return Compat::LogStruct(os)
@ -152,6 +190,38 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_RENDERSTATE& val)
<< val.Value;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETRENDERTARGET& val)
{
return Compat::LogStruct(os)
<< val.RenderTargetIndex
<< val.hRenderTarget
<< val.SubResourceIndex;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCE& val)
{
return Compat::LogStruct(os)
<< val.Stream
<< val.hVertexBuffer
<< val.Offset
<< val.Stride;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_SETSTREAMSOURCEUM& val)
{
return Compat::LogStruct(os)
<< val.Stream
<< val.Stride;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_TEXTURESTAGESTATE& val)
{
return Compat::LogStruct(os)
<< val.Stage
<< val.State
<< val.Value;
}
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_UNLOCK& val)
{
return Compat::LogStruct(os)

View File

@ -12,12 +12,20 @@ std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CLEAR& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_COLORFILL& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATERESOURCE& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_CREATERESOURCE2& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWINDEXEDPRIMITIVE& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWINDEXEDPRIMITIVE2& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWPRIMITIVE& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_DRAWPRIMITIVE2& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_LOCK& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_OPENRESOURCE& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENT& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENT1& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_PRESENTSURFACE& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_RENDERSTATE& val);
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_SETSTREAMSOURCEUM& 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_WINFO& val);
std::ostream& operator<<(std::ostream& os, const D3DDDIARG_ZRANGE& val);

View File

@ -334,6 +334,15 @@ namespace D3dDdi
template <typename Arg>
Resource Resource::create(Device& device, Arg& data, HRESULT(APIENTRY *createResourceFunc)(HANDLE, Arg*))
{
if (D3DDDIFMT_VERTEXDATA == data.Format &&
data.Flags.VertexBuffer &&
data.Flags.MightDrawFromLocked &&
D3DDDIPOOL_SYSTEMMEM != data.Pool)
{
const HRESULT D3DERR_NOTAVAILABLE = 0x8876086A;
throw HResultException(D3DERR_NOTAVAILABLE);
}
Resource resource(device, data);
Arg origData = data;
fixResourceData(device, reinterpret_cast<D3DDDIARG_CREATERESOURCE&>(data));
@ -371,6 +380,31 @@ namespace D3dDdi
}
}
void Resource::fixVertexData(UINT offset, UINT count, UINT stride)
{
if (!m_fixedData.Flags.MightDrawFromLocked ||
!m_fixedData.pSurfList[0].pSysMem ||
!(m_fixedData.Fvf & D3DFVF_XYZRHW))
{
return;
}
unsigned char* data = static_cast<unsigned char*>(const_cast<void*>(m_fixedData.pSurfList[0].pSysMem)) + offset;
if (0.0f != reinterpret_cast<D3DTLVERTEX*>(data)->rhw)
{
return;
}
for (UINT i = 0; i < count; ++i)
{
if (0.0f == reinterpret_cast<D3DTLVERTEX*>(data)->rhw)
{
reinterpret_cast<D3DTLVERTEX*>(data)->rhw = 1.0f;
}
data += stride;
}
}
void* Resource::getLockPtr(UINT subResourceIndex)
{
if (subResourceIndex < m_lockData.size())

View File

@ -28,6 +28,7 @@ namespace D3dDdi
HRESULT blt(D3DDDIARG_BLT data);
HRESULT colorFill(const D3DDDIARG_COLORFILL& data);
void destroy();
void fixVertexData(UINT offset, UINT count, UINT stride);
void* getLockPtr(UINT subResourceIndex);
HRESULT lock(D3DDDIARG_LOCK& data);
void prepareForRendering(UINT subResourceIndex, bool isReadOnly);

View File

@ -198,6 +198,7 @@
<ClInclude Include="Direct3d\Direct3dVertexBuffer.h" />
<ClInclude Include="Direct3d\Direct3dViewport.h" />
<ClInclude Include="Direct3d\Hooks.h" />
<ClInclude Include="Direct3d\Log.h" />
<ClInclude Include="Direct3d\Types.h" />
<ClInclude Include="Direct3d\Visitors\Direct3dDeviceVtblVisitor.h" />
<ClInclude Include="Direct3d\Visitors\Direct3dTextureVtblVisitor.h" />
@ -265,6 +266,7 @@
<ClCompile Include="Direct3d\Direct3dVertexBuffer.cpp" />
<ClCompile Include="Direct3d\Direct3dViewport.cpp" />
<ClCompile Include="Direct3d\Hooks.cpp" />
<ClCompile Include="Direct3d\Log.cpp" />
<ClCompile Include="Dll\Procs.cpp" />
<ClCompile Include="Dll\DllMain.cpp" />
<ClCompile Include="Dll\UnmodifiedProcs.cpp" />

View File

@ -354,6 +354,9 @@
<ClInclude Include="D3dDdi\FormatInfo.h">
<Filter>Header Files\D3dDdi</Filter>
</ClInclude>
<ClInclude Include="Direct3d\Log.h">
<Filter>Header Files\Direct3d</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -539,6 +542,9 @@
<ClCompile Include="D3dDdi\FormatInfo.cpp">
<Filter>Source Files\D3dDdi</Filter>
</ClCompile>
<ClCompile Include="Direct3d\Log.cpp">
<Filter>Source Files\Direct3d</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Dll\DDrawCompat.def">

View File

@ -1,7 +1,8 @@
#pragma once
#include "Common/CompatVtable.h"
#include "Direct3d/Visitors/Direct3dVtblVisitor.h"
#include <Common/CompatVtable.h>
#include <Direct3d/Log.h>
#include <Direct3d/Visitors/Direct3dVtblVisitor.h>
namespace Direct3d
{

View File

@ -1,7 +1,8 @@
#pragma once
#include "Common/CompatVtable.h"
#include "Direct3d/Visitors/Direct3dDeviceVtblVisitor.h"
#include <Common/CompatVtable.h>
#include <Direct3d/Log.h>
#include <Direct3d/Visitors/Direct3dDeviceVtblVisitor.h>
namespace Direct3d
{

View File

@ -1,7 +1,8 @@
#pragma once
#include "Common/CompatVtable.h"
#include "Direct3d/Visitors/Direct3dTextureVtblVisitor.h"
#include <Common/CompatVtable.h>
#include <Direct3d/Log.h>
#include <Direct3d/Visitors/Direct3dTextureVtblVisitor.h>
namespace Direct3d
{

View File

@ -1,7 +1,8 @@
#pragma once
#include "Common/CompatVtable.h"
#include "Direct3d/Visitors/Direct3dVertexBufferVtblVisitor.h"
#include <Common/CompatVtable.h>
#include <Direct3d/Log.h>
#include <Direct3d/Visitors/Direct3dVertexBufferVtblVisitor.h>
namespace Direct3d
{

View File

@ -1,7 +1,8 @@
#pragma once
#include "Common/CompatVtable.h"
#include "Direct3d/Visitors/Direct3dViewportVtblVisitor.h"
#include <Common/CompatVtable.h>
#include <Direct3d/Log.h>
#include <Direct3d/Visitors/Direct3dViewportVtblVisitor.h>
namespace Direct3d
{

View File

@ -0,0 +1,26 @@
#include <Direct3d/Log.h>
std::ostream& operator<<(std::ostream& os, const D3DDP_PTRSTRIDE& data)
{
return Compat::LogStruct(os)
<< data.lpvData
<< data.dwStride;
}
std::ostream& operator<<(std::ostream& os, const D3DDRAWPRIMITIVESTRIDEDDATA& data)
{
return Compat::LogStruct(os)
<< data.position
<< data.normal
<< data.diffuse
<< data.specular
<< Compat::array(data.textureCoords, D3DDP_MAXTEXCOORD);
}
std::ostream& operator<<(std::ostream& os, const D3DVERTEXBUFFERDESC& data)
{
return Compat::LogStruct(os)
<< Compat::hex(data.dwCaps)
<< Compat::hex(data.dwFVF)
<< data.dwNumVertices;
}

View File

@ -0,0 +1,9 @@
#pragma once
#include <d3d.h>
#include <Common/Log.h>
std::ostream& operator<<(std::ostream& os, const D3DDP_PTRSTRIDE& data);
std::ostream& operator<<(std::ostream& os, const D3DDRAWPRIMITIVESTRIDEDDATA& data);
std::ostream& operator<<(std::ostream& os, const D3DVERTEXBUFFERDESC& data);