Skip to content

Commit

Permalink
Partial workaround for black D3DTA_DIFFUSE color on some drivers when…
Browse files Browse the repository at this point in the history
… RHW=0

Fixes black screen issues under some circumstances (e.g. underwater) in
Might and Magic 9 (issue #48).
  • Loading branch information
narzoul committed Aug 10, 2019
1 parent 7068d28 commit bb6092e
Show file tree
Hide file tree
Showing 17 changed files with 213 additions and 15 deletions.
8 changes: 3 additions & 5 deletions DDrawCompat/Common/VtableHookVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

struct _D3DDDI_ADAPTERCALLBACKS;
struct _D3DDDI_ADAPTERFUNCS;
struct _D3DDDI_DEVICEALLBACKS;
struct _D3DDDI_DEVICECALLBACKS;
struct _D3DDDI_DEVICEFUNCS;

template <typename Vtable>
Expand All @@ -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 {};
Expand All @@ -42,9 +42,7 @@ class VtableHookVisitor
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));
}
Expand Down
33 changes: 33 additions & 0 deletions DDrawCompat/D3dDdi/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ namespace D3dDdi
, m_adapter(Adapter::get(adapter))
, m_device(device)
, m_sharedPrimary(nullptr)
, m_streamSourceData{}
, m_streamSource(nullptr)
{
}

Expand Down Expand Up @@ -135,6 +137,10 @@ namespace D3dDdi
g_gdiResourceHandle = nullptr;
g_gdiResource = nullptr;
}
if (resource == m_streamSource)
{
m_streamSource = nullptr;
}
}

return result;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions DDrawCompat/D3dDdi/Device.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
};
Expand Down
2 changes: 2 additions & 0 deletions DDrawCompat/D3dDdi/DeviceFuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
70 changes: 70 additions & 0 deletions DDrawCompat/D3dDdi/Log/DeviceFuncsLog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions DDrawCompat/D3dDdi/Log/DeviceFuncsLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
34 changes: 34 additions & 0 deletions DDrawCompat/D3dDdi/Resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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())
Expand Down
1 change: 1 addition & 0 deletions DDrawCompat/D3dDdi/Resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions DDrawCompat/DDrawCompat.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down Expand Up @@ -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" />
Expand Down
6 changes: 6 additions & 0 deletions DDrawCompat/DDrawCompat.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down Expand Up @@ -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">
Expand Down
5 changes: 3 additions & 2 deletions DDrawCompat/Direct3d/Direct3d.h
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down
5 changes: 3 additions & 2 deletions DDrawCompat/Direct3d/Direct3dDevice.h
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down
5 changes: 3 additions & 2 deletions DDrawCompat/Direct3d/Direct3dTexture.h
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down
5 changes: 3 additions & 2 deletions DDrawCompat/Direct3d/Direct3dVertexBuffer.h
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down
5 changes: 3 additions & 2 deletions DDrawCompat/Direct3d/Direct3dViewport.h
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down
26 changes: 26 additions & 0 deletions DDrawCompat/Direct3d/Log.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
Loading

0 comments on commit bb6092e

Please sign in to comment.