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

Added shader disassembler

This commit is contained in:
narzoul 2023-01-15 23:11:51 +01:00
parent a0d7cffc07
commit 2248a07113
7 changed files with 636 additions and 0 deletions

View File

@ -12,6 +12,7 @@
#include <D3dDdi/DeviceFuncs.h>
#include <D3dDdi/Resource.h>
#include <D3dDdi/ScopedCriticalSection.h>
#include <D3dDdi/ShaderAssembler.h>
#include <DDraw/ScopedThreadLock.h>
namespace
@ -247,6 +248,13 @@ namespace D3dDdi
return m_origVtable.pfnColorFill(m_device, data);
}
HRESULT Device::pfnCreatePixelShader(D3DDDIARG_CREATEPIXELSHADER* data, const UINT* code)
{
LOG_DEBUG << "Pixel shader bytecode: " << Compat::hexDump(code, data->CodeSize);
LOG_DEBUG << ShaderAssembler(code, data->CodeSize).disassemble();
return m_origVtable.pfnCreatePixelShader(m_device, data, code);
}
HRESULT Device::pfnCreateResource(D3DDDIARG_CREATERESOURCE* data)
{
D3DDDIARG_CREATERESOURCE2 data2 = {};
@ -277,6 +285,13 @@ namespace D3dDdi
}
}
HRESULT Device::pfnCreateVertexShaderFunc(D3DDDIARG_CREATEVERTEXSHADERFUNC* data, const UINT* code)
{
LOG_DEBUG << "Vertex shader bytecode: " << Compat::hexDump(code, data->Size);
LOG_DEBUG << ShaderAssembler(code, data->Size).disassemble();
return m_origVtable.pfnCreateVertexShaderFunc(m_device, data, code);
}
HRESULT Device::pfnDepthFill(const D3DDDIARG_DEPTHFILL* data)
{
flushPrimitives();

View File

@ -33,8 +33,10 @@ namespace D3dDdi
HRESULT pfnBlt(const D3DDDIARG_BLT* data);
HRESULT pfnClear(const D3DDDIARG_CLEAR* data, UINT numRect, const RECT* rect);
HRESULT pfnColorFill(const D3DDDIARG_COLORFILL* data);
HRESULT pfnCreatePixelShader(D3DDDIARG_CREATEPIXELSHADER* data, const UINT* code);
HRESULT pfnCreateResource(D3DDDIARG_CREATERESOURCE* data);
HRESULT pfnCreateResource2(D3DDDIARG_CREATERESOURCE2* data);
HRESULT pfnCreateVertexShaderFunc(D3DDDIARG_CREATEVERTEXSHADERFUNC* data, const UINT* code);
HRESULT pfnDepthFill(const D3DDDIARG_DEPTHFILL* data);
HRESULT pfnDestroyDevice();
HRESULT pfnDestroyResource(HANDLE resource);

View File

@ -54,6 +54,8 @@ namespace
SET_DEVICE_FUNC(pfnColorFill);
SET_DEVICE_FUNC(pfnCreateResource);
SET_DEVICE_FUNC(pfnCreateResource2);
SET_DEVICE_FUNC(pfnCreatePixelShader);
SET_DEVICE_FUNC(pfnCreateVertexShaderFunc);
SET_DEVICE_FUNC(pfnDepthFill);
SET_DEVICE_FUNC(pfnDestroyDevice);
SET_DEVICE_FUNC(pfnDestroyResource);

View File

@ -0,0 +1,563 @@
#include <algorithm>
#include <array>
#include <map>
#include <sstream>
#include <d3d9.h>
#include <D3dDdi/ShaderAssembler.h>
namespace
{
const UINT BEGIN_BLOCK = 1;
const UINT END_BLOCK = 2;
typedef std::array<const char*, 7> Controls;
const Controls CMP_CONTROLS = { nullptr, "gt", "eq", "ge", "lt", "ne", "le" };
const Controls TEXLD_CONTROLS = { "", "p", "b" };
struct CommentToken
{
UINT32 opcode : 16;
UINT32 tokenCount : 15;
UINT32 : 1;
};
struct Instruction
{
const char* name;
UINT dstCount = 0;
UINT srcCount = 0;
UINT extraCount = 0;
UINT indent = 0;
const Controls* controls = nullptr;
};
struct InstructionToken
{
UINT32 opcode : 16;
UINT32 control : 8;
UINT32 tokenCount : 4;
UINT32 isPredicated : 1;
UINT32 : 3;
};
struct VersionToken
{
UINT32 minor : 8;
UINT32 major : 8;
UINT32 type : 16;
};
std::map<UINT16, Instruction> g_instructionMap = {
{ D3DSIO_NOP, { "nop" } },
{ D3DSIO_MOV, { "mov", 1, 1 } },
{ D3DSIO_ADD, { "add", 1, 2 } },
{ D3DSIO_SUB, { "sub", 1, 2 } },
{ D3DSIO_MAD, { "mad", 1, 3 } },
{ D3DSIO_MUL, { "mul", 1, 2 } },
{ D3DSIO_RCP, { "rcp", 1, 1 } },
{ D3DSIO_RSQ, { "rsq", 1, 1 } },
{ D3DSIO_DP3, { "dp3", 1, 2 } },
{ D3DSIO_DP4, { "dp4", 1, 2 } },
{ D3DSIO_MIN, { "min", 1, 2 } },
{ D3DSIO_MAX, { "max", 1, 2 } },
{ D3DSIO_SLT, { "slt", 1, 2 } },
{ D3DSIO_SGE, { "sge", 1, 2 } },
{ D3DSIO_EXP, { "exp", 1, 1 } },
{ D3DSIO_LOG, { "log", 1, 1 } },
{ D3DSIO_LIT, { "lit", 1, 1 } },
{ D3DSIO_DST, { "dst", 1, 2 } },
{ D3DSIO_LRP, { "lrp", 1, 3 } },
{ D3DSIO_FRC, { "frc", 1, 1 } },
{ D3DSIO_M4x4, { "m4x4", 1, 2 } },
{ D3DSIO_M4x3, { "m4x3", 1, 2 } },
{ D3DSIO_M3x4, { "m3x4", 1, 2 } },
{ D3DSIO_M3x3, { "m3x3", 1, 2 } },
{ D3DSIO_M3x2, { "m3x2", 1, 2 } },
{ D3DSIO_CALL, { "call", 0, 1 } },
{ D3DSIO_CALLNZ, { "callnz", 0, 2 } },
{ D3DSIO_LOOP, { "loop", 0, 1, 0, BEGIN_BLOCK } },
{ D3DSIO_RET, { "ret" } },
{ D3DSIO_ENDLOOP, { "endloop", 0, 0, 0, END_BLOCK } },
{ D3DSIO_LABEL, { "label", 0, 1 } },
{ D3DSIO_DCL, { "dcl", 1, 0, 1 } },
{ D3DSIO_POW, { "pow", 1, 2 } },
{ D3DSIO_CRS, { "crs", 1, 2 } },
{ D3DSIO_SGN, { "sgn", 1, 3 } },
{ D3DSIO_ABS, { "abs", 1, 1 } },
{ D3DSIO_NRM, { "nrm", 1, 1 } },
{ D3DSIO_SINCOS, { "sincos", 1, 3 } },
{ D3DSIO_REP, { "rep", 0, 1, 0, BEGIN_BLOCK } },
{ D3DSIO_ENDREP, { "endrep", 0, 0, 0, END_BLOCK } },
{ D3DSIO_IF, { "if", 0, 1, 0, BEGIN_BLOCK } },
{ D3DSIO_IFC, { "if_", 0, 2, 0, BEGIN_BLOCK, &CMP_CONTROLS } },
{ D3DSIO_ELSE, { "else", 0, 0, 0, BEGIN_BLOCK | END_BLOCK } },
{ D3DSIO_ENDIF, { "endif", 0, 0, 0, END_BLOCK } },
{ D3DSIO_BREAK, { "break" } },
{ D3DSIO_BREAKC, { "break_", 0, 2, 0, 0, &CMP_CONTROLS } },
{ D3DSIO_MOVA, { "mova", 1, 1 } },
{ D3DSIO_DEFB, { "defb", 1, 0, 1 } },
{ D3DSIO_DEFI, { "defi", 1, 0, 4 } },
{ D3DSIO_TEXKILL, { "texkill", 1 } },
{ D3DSIO_TEX, { "texld", 1, 2, 0, 0, &TEXLD_CONTROLS } },
{ D3DSIO_TEXBEM, { "texbem", 1, 1 } },
{ D3DSIO_TEXBEML, { "texbeml", 1, 1 } },
{ D3DSIO_TEXREG2AR, { "texreg2ar", 1, 1 } },
{ D3DSIO_TEXM3x2PAD, { "texm3x2pad", 1, 1 } },
{ D3DSIO_TEXM3x2TEX, { "texm3x2tex", 1, 1 } },
{ D3DSIO_TEXM3x3PAD, { "texm3x3pad", 1, 1 } },
{ D3DSIO_TEXM3x3TEX, { "texm3x3tex", 1, 1 } },
{ D3DSIO_TEXM3x3SPEC, { "texm3x3spec", 1, 2 } },
{ D3DSIO_TEXM3x3VSPEC, { "texm3x3vspec", 1, 1 } },
{ D3DSIO_EXPP, { "expp", 1, 1 } },
{ D3DSIO_LOGP, { "logp", 1, 1 } },
{ D3DSIO_CND, { "cnd", 1, 3 } },
{ D3DSIO_DEF, { "def", 1, 0, 4 } },
{ D3DSIO_TEXREG2RGB, { "texreg2rgb", 1, 1 } },
{ D3DSIO_TEXDP3TEX, { "texdp3tex", 1, 1 } },
{ D3DSIO_TEXM3x2DEPTH, { "texm3x2depth", 1, 1 } },
{ D3DSIO_TEXDP3, { "texdp3", 1, 1 } },
{ D3DSIO_TEXM3x3, { "texm3x3", 1, 1 } },
{ D3DSIO_TEXDEPTH, { "texdepth", 1 } },
{ D3DSIO_CMP, { "cmp", 1, 3 } },
{ D3DSIO_BEM, { "bem", 1, 2 } },
{ D3DSIO_DP2ADD, { "dp2add", 1, 3 } },
{ D3DSIO_DSX, { "dsx", 1, 1 } },
{ D3DSIO_DSY, { "dsy", 1, 1 } },
{ D3DSIO_TEXLDD, { "texldd", 1, 2 } },
{ D3DSIO_SETP, { "setp_", 1, 2, 0, 0, &CMP_CONTROLS } },
{ D3DSIO_TEXLDL, { "texldl", 1, 2 } },
{ D3DSIO_BREAKP, { "break pred", 0, 1 } },
{ D3DSIO_PHASE, { "phase" } },
{ D3DSIO_COMMENT, { "// " } },
{ D3DSIO_END, { "end" } }
};
std::map<D3DSHADER_PARAM_REGISTER_TYPE, const char*> g_registerMap = {
{ D3DSPR_TEMP, "r" },
{ D3DSPR_INPUT, "v" },
{ D3DSPR_CONST, "c" },
{ D3DSPR_ATTROUT, "oD"},
{ D3DSPR_TEXCRDOUT, "oT" },
{ D3DSPR_CONSTINT, "i" },
{ D3DSPR_COLOROUT, "oD" },
{ D3DSPR_DEPTHOUT, "oDepth" },
{ D3DSPR_SAMPLER, "s" },
{ D3DSPR_CONSTBOOL, "b" },
{ D3DSPR_LABEL, "l" },
{ D3DSPR_PREDICATE, "p" }
};
std::map<UINT, const char*> g_sourceModifierPrefixMap = {
{ D3DSPSM_NEG, "-" },
{ D3DSPSM_BIASNEG, "-" },
{ D3DSPSM_SIGNNEG, "-" },
{ D3DSPSM_COMP, "1-" },
{ D3DSPSM_X2NEG, "-" },
{ D3DSPSM_ABSNEG, "-" },
{ D3DSPSM_NOT, "!" }
};
std::map<UINT, const char*> g_sourceModifierSuffixMap = {
{ D3DSPSM_BIAS, "bias" },
{ D3DSPSM_SIGN, "bx2" },
{ D3DSPSM_X2, "x2" },
{ D3DSPSM_DZ, "dz" },
{ D3DSPSM_DW, "dw" },
{ D3DSPSM_ABS, "abs" }
};
std::map<UINT, const char*> g_textureTypeMap = {
{ D3DSTT_UNKNOWN, nullptr },
{ D3DSTT_2D, "2d" },
{ D3DSTT_CUBE, "cube" },
{ D3DSTT_VOLUME, "volume" }
};
std::map<D3DDECLUSAGE, const char*> g_usageMap = {
{ D3DDECLUSAGE_POSITION, "position" },
{ D3DDECLUSAGE_BLENDWEIGHT, "blendweight" },
{ D3DDECLUSAGE_BLENDINDICES, "blendindices" },
{ D3DDECLUSAGE_NORMAL, "normal" },
{ D3DDECLUSAGE_PSIZE, "psize" },
{ D3DDECLUSAGE_TEXCOORD, "texcoord" },
{ D3DDECLUSAGE_TANGENT, "tangent" },
{ D3DDECLUSAGE_BINORMAL, "binormal" },
{ D3DDECLUSAGE_TESSFACTOR, "tessfactor" },
{ D3DDECLUSAGE_POSITIONT, "positiont" },
{ D3DDECLUSAGE_COLOR, "color" },
{ D3DDECLUSAGE_FOG, "fog" },
{ D3DDECLUSAGE_DEPTH, "depth" },
{ D3DDECLUSAGE_SAMPLE, "sample" }
};
}
namespace D3dDdi
{
ShaderAssembler::ShaderAssembler(const UINT* code, DWORD size)
: m_tokens(code, code + size)
, m_pos(0)
{
}
std::string ShaderAssembler::disassemble()
{
auto origPos = m_pos;
m_pos = 0;
std::ostringstream os;
os << "Disassembled shader code:" << std::endl;
try
{
disassembleVersion(os);
UINT indent = 0;
while (0 != getRemainingTokenCount())
{
os << std::endl;
if (D3DSIO_END == disassembleInstruction(os, indent))
{
break;
}
}
}
catch (std::exception& e)
{
os << e.what();
}
m_pos = origPos;
return os.str();
}
void ShaderAssembler::disassembleComment(std::ostream& os, UINT tokenCount)
{
auto begin = reinterpret_cast<const char*>(readTokens(tokenCount));
auto end = begin + tokenCount * 4;
end = std::find_if(begin, end, [](char c) { return !std::isprint(c); });
os.write(begin, end - begin);
}
void ShaderAssembler::disassembleConstToken(std::ostream& os, UINT opcode)
{
switch (opcode)
{
case D3DSIO_DEFB:
case D3DSIO_DEFI:
os << readToken<INT>();
break;
default:
os << readToken<FLOAT>();
break;
}
}
void ShaderAssembler::disassembleDclPs(std::ostream& os)
{
auto token = readToken();
auto type = token & D3DSP_TEXTURETYPE_MASK;
auto it = g_textureTypeMap.find(type);
if (it == g_textureTypeMap.end())
{
throw std::runtime_error("Unknown dcl texture type: " + std::to_string(type >> D3DSP_TEXTURETYPE_SHIFT));
}
if (it->second)
{
os << '_' << it->second;
}
}
void ShaderAssembler::disassembleDclVs(std::ostream& os)
{
auto token = readToken();
auto usage = static_cast<D3DDECLUSAGE>(token & D3DSP_DCL_USAGE_MASK);
auto it = g_usageMap.find(usage);
if (it == g_usageMap.end())
{
throw std::runtime_error("Unknown dcl usage: " + std::to_string(usage));
}
os << '_' << it->second;
auto usageIndex = (token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
if (0 != usageIndex)
{
os << usageIndex;
}
}
void ShaderAssembler::disassembleDestinationParameter(std::ostream& os)
{
auto token = readToken();
auto dstMod = token & D3DSP_DSTMOD_MASK;
if (dstMod & D3DSPDM_SATURATE)
{
os << "_sat";
}
if (dstMod & D3DSPDM_PARTIALPRECISION)
{
os << "_pp";
}
if (dstMod & D3DSPDM_MSAMPCENTROID)
{
os << "_centroid";
}
os << ' ';
disassembleRegister(os, token);
auto writeMask = token & D3DSP_WRITEMASK_ALL;
if (D3DSP_WRITEMASK_ALL != writeMask)
{
os << '.';
if (writeMask & D3DSP_WRITEMASK_0)
{
os << 'x';
}
if (writeMask & D3DSP_WRITEMASK_1)
{
os << 'y';
}
if (writeMask & D3DSP_WRITEMASK_2)
{
os << 'z';
}
if (writeMask & D3DSP_WRITEMASK_3)
{
os << 'w';
}
}
}
UINT ShaderAssembler::disassembleInstruction(std::ostream& os, UINT& indent)
{
auto token = readToken<InstructionToken>();
auto it = g_instructionMap.find(token.opcode);
if (it == g_instructionMap.end())
{
throw std::runtime_error("Unknown opcode: " + std::to_string(token.opcode));
}
if ((it->second.indent & END_BLOCK) && indent > 0)
{
--indent;
}
os << std::string(2 * indent, ' ') << it->second.name;
if (it->second.indent & BEGIN_BLOCK)
{
++indent;
}
if (D3DSIO_COMMENT == token.opcode)
{
disassembleComment(os, reinterpret_cast<const CommentToken*>(&token)->tokenCount);
return token.opcode;
}
if (0 != token.control || it->second.controls)
{
auto control = (it->second.controls && token.control < it->second.controls->size())
? it->second.controls->at(token.control)
: nullptr;
if (!control)
{
throw std::runtime_error("Unknown control: " + std::to_string(token.control) +
", opcode: " + std::to_string(token.opcode));
}
os << control;
}
auto inst = it->second;
auto extraCount = it->second.extraCount;
auto tokenCount = inst.dstCount + inst.srcCount + extraCount;
if (token.tokenCount != tokenCount)
{
throw std::runtime_error("Instruction length mismatch: expected " + std::to_string(token.tokenCount) +
", got " + std::to_string(tokenCount) + ", opcode: " + std::to_string(token.opcode));
}
if (D3DSIO_DCL == token.opcode)
{
if (Pixel == getShaderType())
{
disassembleDclPs(os);
}
else
{
disassembleDclVs(os);
}
--extraCount;
}
const char* separator = " ";
if (it->second.dstCount)
{
disassembleDestinationParameter(os);
separator = ", ";
}
for (UINT i = 0; i < it->second.srcCount; ++i)
{
os << separator;
disassembleSourceParameter(os);
separator = ", ";
}
for (UINT i = 0; i < extraCount; ++i)
{
os << separator;
disassembleConstToken(os, token.opcode);
separator = ", ";
}
return token.opcode;
}
void ShaderAssembler::disassembleRegister(std::ostream& os, UINT token)
{
auto registerType = static_cast<D3DSHADER_PARAM_REGISTER_TYPE>(
((token & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) |
((token & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2));
auto registerNumber = token & D3DSP_REGNUM_MASK;
auto it = g_registerMap.find(registerType);
if (it != g_registerMap.end())
{
os << it->second << registerNumber;
return;
}
switch (registerType)
{
case D3DSPR_ADDR:
os << (Pixel == getShaderType() ? 't' : 'a') << registerNumber;
break;
case D3DSPR_RASTOUT:
switch (registerNumber)
{
case D3DSRO_POSITION:
os << "oPos";
break;
case D3DSRO_FOG:
os << "oFog";
break;
case D3DSRO_POINT_SIZE:
os << "oPts";
break;
default:
throw std::runtime_error("Unknown rasterizer output register number: " + std::to_string(registerNumber));
}
break;
case D3DSPR_CONST2:
case D3DSPR_CONST3:
case D3DSPR_CONST4:
os << 'c' << (registerType - D3DSPR_CONST2 + 1) * 2048 + registerNumber;
break;
default:
os << "reg" << registerType << '/' << registerNumber;
break;
}
}
void ShaderAssembler::disassembleSourceParameter(std::ostream& os)
{
auto token = readToken();
auto modifier = token & D3DSP_SRCMOD_MASK;
auto it = g_sourceModifierPrefixMap.find(modifier);
if (it != g_sourceModifierPrefixMap.end())
{
os << it->second;
}
disassembleRegister(os, token);
it = g_sourceModifierSuffixMap.find(modifier);
if (it != g_sourceModifierSuffixMap.end())
{
os << '_' << it->second;
}
disassembleSourceSwizzle(os, token);
}
void ShaderAssembler::disassembleSourceSwizzle(std::ostream& os, UINT token)
{
const char component[] = { 'x', 'y', 'z', 'w' };
UINT swizzle = token & D3DVS_SWIZZLE_MASK;
switch (swizzle)
{
case D3DSP_NOSWIZZLE:
break;
case D3DSP_REPLICATERED:
case D3DSP_REPLICATEGREEN:
case D3DSP_REPLICATEBLUE:
case D3DSP_REPLICATEALPHA:
os << '.' << component[(swizzle >> D3DVS_SWIZZLE_SHIFT) & 0x3];
break;
default:
os << '.';
swizzle >>= D3DVS_SWIZZLE_SHIFT;
for (UINT i = 0; i < 4; ++i)
{
os << component[swizzle & 0x3];
swizzle >>= 2;
}
break;
}
}
void ShaderAssembler::disassembleVersion(std::ostream& os)
{
auto version = readToken<VersionToken>();
os << ((Pixel == version.type) ? "ps" : "vs")
<< '_' << static_cast<UINT>(version.major)
<< '_' << static_cast<UINT>(version.minor);
if (2 != version.major || 0 != version.minor)
{
throw std::runtime_error("Unsupported shader version");
}
}
UINT ShaderAssembler::getRemainingTokenCount() const
{
return m_tokens.size() - m_pos;
}
ShaderAssembler::ShaderType ShaderAssembler::getShaderType() const
{
return static_cast<ShaderType>(m_tokens.front() >> 16);
}
UINT ShaderAssembler::readToken()
{
return *readTokens(1);
}
template <typename Token>
Token ShaderAssembler::readToken()
{
static_assert(4 == sizeof(Token));
return *reinterpret_cast<const Token*>(readTokens(1));
}
const UINT* ShaderAssembler::readTokens(UINT count)
{
if (count > getRemainingTokenCount())
{
throw std::runtime_error("Unexpected end of code");
}
auto tokens = m_tokens.data() + m_pos;
m_pos += count;
return tokens;
}
}

View File

@ -0,0 +1,46 @@
#pragma once
#include <ostream>
#include <string>
#include <vector>
#include <Windows.h>
namespace D3dDdi
{
class ShaderAssembler
{
public:
ShaderAssembler(const UINT* code, DWORD size);
std::string disassemble();
private:
enum ShaderType
{
Vertex = 0xFFFE,
Pixel = 0xFFFF
};
void disassembleComment(std::ostream& os, UINT tokenCount);
void disassembleConstToken(std::ostream& os, UINT opcode);
void disassembleDclPs(std::ostream& os);
void disassembleDclVs(std::ostream& os);
void disassembleDestinationParameter(std::ostream& os);
UINT disassembleInstruction(std::ostream& os, UINT& indent);
void disassembleRegister(std::ostream& os, UINT token);
void disassembleSourceParameter(std::ostream& os);
void disassembleSourceSwizzle(std::ostream& os, UINT token);
void disassembleVersion(std::ostream& os);
UINT getRemainingTokenCount() const;
ShaderType getShaderType() const;
UINT readToken();
const UINT* readTokens(UINT count);
template <typename Token>
Token readToken();
std::vector<UINT> m_tokens;
UINT m_pos;
};
}

View File

@ -221,6 +221,7 @@
<ClInclude Include="D3dDdi\Resource.h" />
<ClInclude Include="D3dDdi\ResourceDeleter.h" />
<ClInclude Include="D3dDdi\ScopedCriticalSection.h" />
<ClInclude Include="D3dDdi\ShaderAssembler.h" />
<ClInclude Include="D3dDdi\ShaderBlitter.h" />
<ClInclude Include="D3dDdi\SurfaceRepository.h" />
<ClInclude Include="D3dDdi\Visitors\AdapterCallbacksVisitor.h" />
@ -369,6 +370,7 @@
<ClCompile Include="D3dDdi\Log\KernelModeThunksLog.cpp" />
<ClCompile Include="D3dDdi\Resource.cpp" />
<ClCompile Include="D3dDdi\ScopedCriticalSection.cpp" />
<ClCompile Include="D3dDdi\ShaderAssembler.cpp" />
<ClCompile Include="D3dDdi\ShaderBlitter.cpp" />
<ClCompile Include="D3dDdi\SurfaceRepository.cpp" />
<ClCompile Include="DDraw\Blitter.cpp" />

View File

@ -660,6 +660,9 @@
<ClInclude Include="Config\Settings\DesktopResolution.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
<ClInclude Include="D3dDdi\ShaderAssembler.h">
<Filter>Header Files\D3dDdi</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -1043,6 +1046,9 @@
<ClCompile Include="Config\Settings\DesktopResolution.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
<ClCompile Include="D3dDdi\ShaderAssembler.cpp">
<Filter>Source Files\D3dDdi</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DDrawCompat.rc">