https://git.reactos.org/?p=reactos.git;a=commitdiff;h=afbc458a7f55aab4480d3…
commit afbc458a7f55aab4480d316a9946c3fc47cefebe
Author: winesync <ros-dev(a)reactos.org>
AuthorDate: Sat Feb 1 18:02:26 2020 +0100
Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com>
CommitDate: Wed Feb 26 18:19:18 2020 +0100
[WINESYNC] d3dx9_36: Implement D3DXDisassembleShader. (v2)
Changes in v2 (by Christian Costa):
* More generic code for D3DXDisassembleShader.
wine-staging patch by Christian Costa <titan.costa(a)gmail.com>
---
dll/directx/wine/d3dx9_36/shader.c | 330 ++++++++++++++++++-
..._36__Implement_D3DXDisassembleShader._(v2).diff | 357 +++++++++++++++++++++
2 files changed, 685 insertions(+), 2 deletions(-)
diff --git a/dll/directx/wine/d3dx9_36/shader.c b/dll/directx/wine/d3dx9_36/shader.c
index e8ce3dd796c..7a23867ba31 100644
--- a/dll/directx/wine/d3dx9_36/shader.c
+++ b/dll/directx/wine/d3dx9_36/shader.c
@@ -1,6 +1,7 @@
/*
* Copyright 2008 Luis Busquets
* Copyright 2009 Matteo Bruni
+ * Copyright 2010, 2013, 2016 Christian Costa
* Copyright 2011 Travis Athougies
*
* This library is free software; you can redistribute it and/or
@@ -20,6 +21,7 @@
#include "config.h"
#include "wine/port.h"
+#include <stdio.h>
#include "d3dx9_private.h"
#include "d3dcommon.h"
@@ -2140,10 +2142,334 @@ HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code,
const char **sample
return D3D_OK;
}
+
+static const char *decl_usage[] = { "position", "blendweight",
"blendindices", "normal", "psize", "texcoord",
+ "tangent", "binormal",
"tessfactor", "positiont", "color" };
+
+static const char *tex_type[] = { "", "1d", "2d",
"cube", "volume" };
+
+static int add_modifier(char *buffer, DWORD param)
+{
+ char *buf = buffer;
+ DWORD dst_mod = param & D3DSP_DSTMOD_MASK;
+
+ if (dst_mod & D3DSPDM_SATURATE)
+ buf += sprintf(buf, "_sat");
+ if (dst_mod & D3DSPDM_PARTIALPRECISION)
+ buf += sprintf(buf, "_pp");
+ if (dst_mod & D3DSPDM_MSAMPCENTROID)
+ buf += sprintf(buf, "_centroid");
+
+ return buf - buffer;
+}
+
+static int add_register(char *buffer, DWORD param, BOOL dst, BOOL ps)
+{
+ char *buf = buffer;
+ DWORD reg_type = ((param & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2)
+ | ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+ DWORD reg_num = param & D3DSP_REGNUM_MASK;
+
+ if (reg_type == D3DSPR_INPUT)
+ buf += sprintf(buf, "v%d", reg_num);
+ else if (reg_type == D3DSPR_CONST)
+ buf += sprintf(buf, "c%d", reg_num);
+ else if (reg_type == D3DSPR_TEMP)
+ buf += sprintf(buf, "r%d", reg_num);
+ else if (reg_type == D3DSPR_ADDR)
+ buf += sprintf(buf, "%s%d", ps ? "t" : "a",
reg_num);
+ else if (reg_type == D3DSPR_SAMPLER)
+ buf += sprintf(buf, "s%d", reg_num);
+ else if (reg_type == D3DSPR_RASTOUT)
+ buf += sprintf(buf, "oPos");
+ else if (reg_type == D3DSPR_COLOROUT)
+ buf += sprintf(buf, "oC%d", reg_num);
+ else if (reg_type == D3DSPR_TEXCRDOUT)
+ buf += sprintf(buf, "oT%d", reg_num);
+ else if (reg_type == D3DSPR_ATTROUT)
+ buf += sprintf(buf, "oD%d", reg_num);
+ else
+ buf += sprintf(buf, "? (%d)", reg_type);
+
+ if (dst)
+ {
+ if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL)
+ {
+ buf += sprintf(buf, ".%s%s%s%s", param & D3DSP_WRITEMASK_0 ?
"x" : "",
+ param & D3DSP_WRITEMASK_1 ?
"y" : "",
+ param & D3DSP_WRITEMASK_2 ?
"z" : "",
+ param & D3DSP_WRITEMASK_3 ?
"w" : "");
+ }
+ }
+ else
+ {
+ if ((param & D3DVS_SWIZZLE_MASK) != D3DVS_NOSWIZZLE)
+ {
+ if ( ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_X | D3DVS_Y_X | D3DVS_Z_X
| D3DVS_W_X)) ||
+ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Y | D3DVS_Y_Y | D3DVS_Z_Y
| D3DVS_W_Y)) ||
+ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Z | D3DVS_Y_Z | D3DVS_Z_Z
| D3DVS_W_Z)) ||
+ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_W | D3DVS_Y_W | D3DVS_Z_W
| D3DVS_W_W)) )
+ buf += sprintf(buf, ".%c", 'w' + (((param >>
D3DVS_SWIZZLE_SHIFT) + 1) & 0x3));
+ else
+ buf += sprintf(buf, ".%c%c%c%c", 'w' + (((param
>> (D3DVS_SWIZZLE_SHIFT+0)) + 1) & 0x3),
+ 'w' + (((param >>
(D3DVS_SWIZZLE_SHIFT+2)) + 1) & 0x3),
+ 'w' + (((param >>
(D3DVS_SWIZZLE_SHIFT+4)) + 1) & 0x3),
+ 'w' + (((param >>
(D3DVS_SWIZZLE_SHIFT+6)) + 1) & 0x3));
+ }
+ }
+
+ return buf - buffer;
+}
+
+struct instr_info
+{
+ DWORD opcode;
+ const char *name;
+ int length;
+ int (*function)(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps);
+ WORD min_version;
+ WORD max_version;
+};
+
+static int instr_comment(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL
ps)
+{
+ *ptr += 1 + ((**ptr & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT);
+ return 0;
+}
+
+static int instr_def(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
+{
+ int len = sprintf(buffer, " def c%d, %g, %g, %g, %g\n", *(*ptr+1) &
D3DSP_REGNUM_MASK,
+ (double)*(float*)(*ptr+2), (double)*(float*)(*ptr+3),
+ (double)*(float*)(*ptr+4), (double)*(float*)(*ptr+5));
+ *ptr += 6;
+ return len;
+}
+
+static int instr_dcl(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
+{
+ DWORD param1 = *++*ptr;
+ DWORD param2 = *++*ptr;
+ DWORD usage = (param1 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+ DWORD usage_index = (param1 & D3DSP_DCL_USAGEINDEX_MASK) >>
D3DSP_DCL_USAGEINDEX_SHIFT;
+ char *buf = buffer;
+
+ buf += sprintf(buf, " dcl");
+ if (ps)
+ {
+ if (param1 & D3DSP_TEXTURETYPE_MASK)
+ buf += sprintf(buf, "_%s", (usage <= D3DSTT_VOLUME) ?
+ tex_type[(param1 & D3DSP_TEXTURETYPE_MASK) >>
D3DSP_TEXTURETYPE_SHIFT] : "???");
+ }
+ else
+ {
+ buf += sprintf(buf, "_%s", (usage <= D3DDECLUSAGE_COLOR) ?
decl_usage[usage] : "???");
+ if (usage_index)
+ buf += sprintf(buf, "%d", usage_index);
+ }
+
+ buf += add_modifier(buf, param2);
+ buf += sprintf(buf, " ");
+ buf += add_register(buf, param2, TRUE, TRUE);
+ buf += sprintf(buf, "\n");
+ (*ptr)++;
+ return buf - buffer;
+}
+
+static int instr_generic(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL
ps)
+{
+ char *buf = buffer;
+ int j;
+
+ buf += sprintf(buf, " %s", info->name);
+ (*ptr)++;
+
+ if (info->length)
+ {
+ buf += add_modifier(buf, **ptr);
+
+ for (j = 0; j < info->length; j++)
+ {
+ buf += sprintf(buf, "%s ", j ? "," : "");
+
+ if ((j != 0) && ((**ptr & D3DSP_SRCMOD_MASK) != D3DSPSM_NONE))
+ {
+ if ((**ptr & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG)
+ buf += sprintf(buf, "-");
+ else
+ buf += sprintf(buf, "*");
+ }
+
+ buf += add_register(buf, **ptr, j == 0, ps);
+
+ if (*(*ptr)++ & D3DVS_ADDRESSMODE_MASK)
+ {
+ buf += sprintf(buf, "[");
+ buf += add_register(buf, **ptr, FALSE, FALSE);
+ buf += sprintf(buf, "]");
+ (*ptr)++;
+ }
+ }
+ }
+ buf += sprintf(buf, "\n");
+ return buf - buffer;
+}
+
+const struct instr_info instructions[] =
+{
+ { D3DSIO_NOP, "nop", 0, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_MOV, "mov", 2, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_ADD, "add", 3, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_SUB, "sub", 3, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_MAD, "mad", 4, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_MUL, "mul", 3, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_RCP, "rcp", 2, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_RSQ, "rsq", 2, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_DP3, "dp3", 3, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_DP4, "dp4", 3, instr_generic, 0x0100, 0xFFFF },
/* >= 1.2 for PS */
+ { D3DSIO_MIN, "min", 3, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_MAX, "max", 3, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_SLT, "slt", 3, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_SGE, "sge", 3, instr_generic, 0x0100, 0xFFFF },
/* VS only */
+ { D3DSIO_EXP, "exp", 2, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_LOG, "log", 2, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_LIT, "lit", 2, instr_generic, 0x0100, 0xFFFF },
/* VS only */
+ { D3DSIO_DST, "dst", 3, instr_generic, 0x0100, 0xFFFF },
/* VS only */
+ { D3DSIO_LRP, "lrp", 4, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for VS */
+ { D3DSIO_FRC, "frc", 2, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_M4x4, "m4x4", 3, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_M4x3, "m4x3", 3, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_M3x4, "m3x4", 3, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_M3x3, "m3x3", 3, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_M3x2, "m3x2", 3, instr_generic, 0x0100, 0xFFFF },
/* >= 2.0 for PS */
+ { D3DSIO_CALL, "call", 1, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_CALLNZ, "callnz", 2, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_LOOP, "loop", 2, instr_generic, 0x0200, 0xFFFF },
/* >= 3.0 for PS */
+ { D3DSIO_RET, "ret", 0, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_ENDLOOP, "endloop", 1, instr_generic, 0x0200, 0xFFFF },
/* >= 3.0 for PS */
+ { D3DSIO_LABEL, "label", 1, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_DCL, "dcl", 1, instr_dcl, 0x0100, 0xFFFF
},
+ { D3DSIO_POW, "pow", 3, instr_generic, 0x0200, 0xFFFF
},
+ { D3DSIO_CRS, "crs", 3, instr_generic, 0x0200, 0xFFFF
},
+ { D3DSIO_SGN, "sgn", 4, instr_generic, 0x0200, 0xFFFF },
/* VS only */
+ { D3DSIO_ABS, "abs", 2, instr_generic, 0x0200, 0xFFFF
},
+ { D3DSIO_NRM, "nrm", 2, instr_generic, 0x0200, 0xFFFF
},
+ { D3DSIO_SINCOS, "sincos", 4, instr_generic, 0x0200, 0x02FF
},
+ { D3DSIO_SINCOS, "sincos", 2, instr_generic, 0x0300, 0xFFFF
},
+ { D3DSIO_REP, "rep", 1, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_ENDREP, "endrep", 0, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_IF, "if", 1, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_IFC, "if_comp", 2, instr_generic, 0x0200, 0xFFFF
},
+ { D3DSIO_ELSE, "else", 0, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_ENDIF, "endif", 0, instr_generic, 0x0200, 0xFFFF },
/* >= 2.a for PS */
+ { D3DSIO_BREAK, "break", 0, instr_generic, 0x0201, 0xFFFF
},
+ { D3DSIO_BREAKC, "break_comp", 2, instr_generic, 0x0201, 0xFFFF
},
+ { D3DSIO_MOVA, "mova", 2, instr_generic, 0x0200, 0xFFFF },
/* VS only */
+ { D3DSIO_DEFB, "defb", 2, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_DEFI, "defi", 2, instr_generic, 0x0100, 0xFFFF
},
+ { D3DSIO_TEXCOORD, "texcoord", 1, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXCOORD, "texcrd", 2, instr_generic, 0x0104, 0x0104 },
/* PS only */
+ { D3DSIO_TEXKILL, "texkill", 1, instr_generic, 0x0100, 0xFFFF },
/* PS only */
+ { D3DSIO_TEX, "tex", 1, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEX, "texld", 2, instr_generic, 0x0104, 0x0104 },
/* PS only */
+ { D3DSIO_TEX, "texld", 3, instr_generic, 0x0200, 0xFFFF },
/* PS only */
+ { D3DSIO_TEXBEM, "texbem", 2, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXBEML, "texbeml", 2, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXREG2AR, "texreg2ar", 2, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXREG2GB, "texreg2gb", 2, instr_generic, 0x0102, 0x0103 },
/* PS only */
+ { D3DSIO_TEXM3x2PAD, "texm3x2pad", 2, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXM3x2TEX, "texm3x2tex", 2, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXM3x3PAD, "texm3x3pad", 2, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXM3x3TEX, "texm3x3tex", 2, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXM3x3DIFF, "texm3x3diff", 2, instr_generic, 0x0100, 0xFFFF },
/* PS only - Not documented */
+ { D3DSIO_TEXM3x3SPEC, "texm3x3spec", 3, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_TEXM3x3VSPEC, "texm3x3vspec", 2, instr_generic, 0x0100, 0x0103 },
/* PS only */
+ { D3DSIO_EXPP, "expp", 2, instr_generic, 0x0100, 0xFFFF },
/* VS only */
+ { D3DSIO_LOGP, "logp", 2, instr_generic, 0x0100, 0xFFFF },
/* VS only */
+ { D3DSIO_CND, "cnd", 4, instr_generic, 0x0100, 0x0104 },
/* PS only */
+ { D3DSIO_DEF, "def", 5, instr_def, 0x0100, 0xFFFF
},
+ { D3DSIO_TEXREG2RGB, "texreg2rgb", 2, instr_generic, 0x0102, 0x0103 },
/* PS only */
+ { D3DSIO_TEXDP3TEX, "texdp3tex", 2, instr_generic, 0x0102, 0x0103 },
/* PS only */
+ { D3DSIO_TEXM3x2DEPTH, "texm3x2depth", 2, instr_generic, 0x0103, 0x0103 },
/* PS only */
+ { D3DSIO_TEXDP3, "texdp3", 2, instr_generic, 0x0102, 0x0103 },
/* PS only */
+ { D3DSIO_TEXM3x3, "texm3x3", 2, instr_generic, 0x0102, 0x0103 },
/* PS only */
+ { D3DSIO_TEXDEPTH, "texdepth", 1, instr_generic, 0x0104, 0x0104 },
/* PS only */
+ { D3DSIO_CMP, "cmp", 4, instr_generic, 0x0102, 0xFFFF },
/* PS only */
+ { D3DSIO_BEM, "bem", 3, instr_generic, 0x0104, 0x0104 },
/* PS only */
+ { D3DSIO_DP2ADD, "dp2add", 4, instr_generic, 0x0200, 0xFFFF },
/* PS only */
+ { D3DSIO_DSX, "dsx", 2, instr_generic, 0x0201, 0xFFFF },
/* PS only */
+ { D3DSIO_DSY, "dsy", 2, instr_generic, 0x0201, 0xFFFF },
/* PS only */
+ { D3DSIO_TEXLDD, "texldd", 5, instr_generic, 0x0201, 0xFFFF },
/* PS only - not existing for 2.b */
+ { D3DSIO_SETP, "setp_comp", 3, instr_generic, 0x0201, 0xFFFF
},
+ { D3DSIO_TEXLDL, "texldl", 3, instr_generic, 0x0300, 0xFFFF
},
+ { D3DSIO_BREAKP, "breakp", 1, instr_generic, 0x0201, 0xFFFF
},
+ { D3DSIO_PHASE, "phase", 0, instr_generic, 0x0104, 0x0104 },
/* PS only */
+ { D3DSIO_COMMENT, "", 0, instr_comment, 0x0100, 0xFFFF }
+};
+
HRESULT WINAPI D3DXDisassembleShader(const DWORD *shader, BOOL colorcode, const char
*comments, ID3DXBuffer **disassembly)
{
- FIXME("%p %d %s %p: stub\n", shader, colorcode, debugstr_a(comments),
disassembly);
- return E_OUTOFMEMORY;
+ DWORD *ptr = (DWORD *)shader;
+ char *buffer, *buf;
+ UINT capacity = 4096;
+ BOOL ps;
+ WORD version;
+ HRESULT hr;
+
+ TRACE("%p %d %s %p\n", shader, colorcode, debugstr_a(comments),
disassembly);
+
+ if (!shader || !disassembly)
+ return D3DERR_INVALIDCALL;
+
+ buf = buffer = HeapAlloc(GetProcessHeap(), 0, capacity);
+ if (!buffer)
+ return E_OUTOFMEMORY;
+
+ ps = (*ptr >> 16) & 1;
+ version = *ptr & 0xFFFF;
+ buf += sprintf(buf, " %s_%d_%d\n", ps ? "ps" : "vs",
D3DSHADER_VERSION_MAJOR(*ptr), D3DSHADER_VERSION_MINOR(*ptr));
+ ptr++;
+
+ while (*ptr != D3DSIO_END)
+ {
+ DWORD index;
+
+ if ((buf - buffer + 128) > capacity)
+ {
+ UINT count = buf - buffer;
+ char *new_buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, capacity * 2);
+ if (!new_buffer)
+ {
+ HeapFree(GetProcessHeap(), 0, buffer);
+ return E_OUTOFMEMORY;
+ }
+ capacity *= 2;
+ buffer = new_buffer;
+ buf = buffer + count;
+ }
+
+ for (index = 0; index < sizeof(instructions)/sizeof(instructions[0]);
index++)
+ if (((*ptr & D3DSI_OPCODE_MASK) == instructions[index].opcode)
&&
+ (version >= instructions[index].min_version) && (version <=
instructions[index].max_version))
+ break;
+
+ if (index != sizeof(instructions)/sizeof(instructions[0]))
+ {
+ buf += instructions[index].function(&(instructions[index]), &ptr,
buf, ps);
+ }
+ else
+ {
+ buf += sprintf(buf, " ??? (Unknown opcode %x)\n", *ptr);
+ while (*++ptr & (1u << 31));
+ }
+ }
+
+ hr = D3DXCreateBuffer(buf - buffer + 1 , disassembly);
+ if (SUCCEEDED(hr))
+ strcpy(ID3DXBuffer_GetBufferPointer(*disassembly), buffer);
+ HeapFree(GetProcessHeap(), 0, buffer);
+
+ return hr;
}
struct d3dx9_texture_shader
diff --git
a/sdk/tools/winesync/d3dx9_staging/0005-d3dx9_36__Implement_D3DXDisassembleShader._(v2).diff
b/sdk/tools/winesync/d3dx9_staging/0005-d3dx9_36__Implement_D3DXDisassembleShader._(v2).diff
new file mode 100644
index 00000000000..f63d8a87887
--- /dev/null
+++
b/sdk/tools/winesync/d3dx9_staging/0005-d3dx9_36__Implement_D3DXDisassembleShader._(v2).diff
@@ -0,0 +1,357 @@
+diff --git a/dll/directx/wine/d3dx9_36/shader.c b/dll/directx/wine/d3dx9_36/shader.c
+index e8ce3dd..7a23867 100644
+--- a/dll/directx/wine/d3dx9_36/shader.c
++++ b/dll/directx/wine/d3dx9_36/shader.c
+@@ -1,6 +1,7 @@
+ /*
+ * Copyright 2008 Luis Busquets
+ * Copyright 2009 Matteo Bruni
++ * Copyright 2010, 2013, 2016 Christian Costa
+ * Copyright 2011 Travis Athougies
+ *
+ * This library is free software; you can redistribute it and/or
+@@ -20,6 +21,7 @@
+
+ #include "config.h"
+ #include "wine/port.h"
++#include <stdio.h>
+
+ #include "d3dx9_private.h"
+ #include "d3dcommon.h"
+@@ -2140,10 +2142,334 @@ HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code,
const char **sample
+ return D3D_OK;
+ }
+
++
++static const char *decl_usage[] = { "position", "blendweight",
"blendindices", "normal", "psize", "texcoord",
++ "tangent", "binormal",
"tessfactor", "positiont", "color" };
++
++static const char *tex_type[] = { "", "1d", "2d",
"cube", "volume" };
++
++static int add_modifier(char *buffer, DWORD param)
++{
++ char *buf = buffer;
++ DWORD dst_mod = param & D3DSP_DSTMOD_MASK;
++
++ if (dst_mod & D3DSPDM_SATURATE)
++ buf += sprintf(buf, "_sat");
++ if (dst_mod & D3DSPDM_PARTIALPRECISION)
++ buf += sprintf(buf, "_pp");
++ if (dst_mod & D3DSPDM_MSAMPCENTROID)
++ buf += sprintf(buf, "_centroid");
++
++ return buf - buffer;
++}
++
++static int add_register(char *buffer, DWORD param, BOOL dst, BOOL ps)
++{
++ char *buf = buffer;
++ DWORD reg_type = ((param & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2)
++ | ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
++ DWORD reg_num = param & D3DSP_REGNUM_MASK;
++
++ if (reg_type == D3DSPR_INPUT)
++ buf += sprintf(buf, "v%d", reg_num);
++ else if (reg_type == D3DSPR_CONST)
++ buf += sprintf(buf, "c%d", reg_num);
++ else if (reg_type == D3DSPR_TEMP)
++ buf += sprintf(buf, "r%d", reg_num);
++ else if (reg_type == D3DSPR_ADDR)
++ buf += sprintf(buf, "%s%d", ps ? "t" : "a",
reg_num);
++ else if (reg_type == D3DSPR_SAMPLER)
++ buf += sprintf(buf, "s%d", reg_num);
++ else if (reg_type == D3DSPR_RASTOUT)
++ buf += sprintf(buf, "oPos");
++ else if (reg_type == D3DSPR_COLOROUT)
++ buf += sprintf(buf, "oC%d", reg_num);
++ else if (reg_type == D3DSPR_TEXCRDOUT)
++ buf += sprintf(buf, "oT%d", reg_num);
++ else if (reg_type == D3DSPR_ATTROUT)
++ buf += sprintf(buf, "oD%d", reg_num);
++ else
++ buf += sprintf(buf, "? (%d)", reg_type);
++
++ if (dst)
++ {
++ if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL)
++ {
++ buf += sprintf(buf, ".%s%s%s%s", param & D3DSP_WRITEMASK_0 ?
"x" : "",
++ param & D3DSP_WRITEMASK_1 ?
"y" : "",
++ param & D3DSP_WRITEMASK_2 ?
"z" : "",
++ param & D3DSP_WRITEMASK_3 ?
"w" : "");
++ }
++ }
++ else
++ {
++ if ((param & D3DVS_SWIZZLE_MASK) != D3DVS_NOSWIZZLE)
++ {
++ if ( ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_X | D3DVS_Y_X | D3DVS_Z_X
| D3DVS_W_X)) ||
++ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Y | D3DVS_Y_Y | D3DVS_Z_Y
| D3DVS_W_Y)) ||
++ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_Z | D3DVS_Y_Z | D3DVS_Z_Z
| D3DVS_W_Z)) ||
++ ((param & D3DSP_SWIZZLE_MASK) == (D3DVS_X_W | D3DVS_Y_W | D3DVS_Z_W
| D3DVS_W_W)) )
++ buf += sprintf(buf, ".%c", 'w' + (((param >>
D3DVS_SWIZZLE_SHIFT) + 1) & 0x3));
++ else
++ buf += sprintf(buf, ".%c%c%c%c", 'w' + (((param
>> (D3DVS_SWIZZLE_SHIFT+0)) + 1) & 0x3),
++ 'w' + (((param >>
(D3DVS_SWIZZLE_SHIFT+2)) + 1) & 0x3),
++ 'w' + (((param >>
(D3DVS_SWIZZLE_SHIFT+4)) + 1) & 0x3),
++ 'w' + (((param >>
(D3DVS_SWIZZLE_SHIFT+6)) + 1) & 0x3));
++ }
++ }
++
++ return buf - buffer;
++}
++
++struct instr_info
++{
++ DWORD opcode;
++ const char *name;
++ int length;
++ int (*function)(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps);
++ WORD min_version;
++ WORD max_version;
++};
++
++static int instr_comment(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL
ps)
++{
++ *ptr += 1 + ((**ptr & D3DSI_COMMENTSIZE_MASK) >>
D3DSI_COMMENTSIZE_SHIFT);
++ return 0;
++}
++
++static int instr_def(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
++{
++ int len = sprintf(buffer, " def c%d, %g, %g, %g, %g\n", *(*ptr+1) &
D3DSP_REGNUM_MASK,
++ (double)*(float*)(*ptr+2), (double)*(float*)(*ptr+3),
++ (double)*(float*)(*ptr+4), (double)*(float*)(*ptr+5));
++ *ptr += 6;
++ return len;
++}
++
++static int instr_dcl(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL ps)
++{
++ DWORD param1 = *++*ptr;
++ DWORD param2 = *++*ptr;
++ DWORD usage = (param1 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
++ DWORD usage_index = (param1 & D3DSP_DCL_USAGEINDEX_MASK) >>
D3DSP_DCL_USAGEINDEX_SHIFT;
++ char *buf = buffer;
++
++ buf += sprintf(buf, " dcl");
++ if (ps)
++ {
++ if (param1 & D3DSP_TEXTURETYPE_MASK)
++ buf += sprintf(buf, "_%s", (usage <= D3DSTT_VOLUME) ?
++ tex_type[(param1 & D3DSP_TEXTURETYPE_MASK) >>
D3DSP_TEXTURETYPE_SHIFT] : "???");
++ }
++ else
++ {
++ buf += sprintf(buf, "_%s", (usage <= D3DDECLUSAGE_COLOR) ?
decl_usage[usage] : "???");
++ if (usage_index)
++ buf += sprintf(buf, "%d", usage_index);
++ }
++
++ buf += add_modifier(buf, param2);
++ buf += sprintf(buf, " ");
++ buf += add_register(buf, param2, TRUE, TRUE);
++ buf += sprintf(buf, "\n");
++ (*ptr)++;
++ return buf - buffer;
++}
++
++static int instr_generic(const struct instr_info *info, DWORD **ptr, char *buffer, BOOL
ps)
++{
++ char *buf = buffer;
++ int j;
++
++ buf += sprintf(buf, " %s", info->name);
++ (*ptr)++;
++
++ if (info->length)
++ {
++ buf += add_modifier(buf, **ptr);
++
++ for (j = 0; j < info->length; j++)
++ {
++ buf += sprintf(buf, "%s ", j ? "," : "");
++
++ if ((j != 0) && ((**ptr & D3DSP_SRCMOD_MASK) != D3DSPSM_NONE))
++ {
++ if ((**ptr & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG)
++ buf += sprintf(buf, "-");
++ else
++ buf += sprintf(buf, "*");
++ }
++
++ buf += add_register(buf, **ptr, j == 0, ps);
++
++ if (*(*ptr)++ & D3DVS_ADDRESSMODE_MASK)
++ {
++ buf += sprintf(buf, "[");
++ buf += add_register(buf, **ptr, FALSE, FALSE);
++ buf += sprintf(buf, "]");
++ (*ptr)++;
++ }
++ }
++ }
++ buf += sprintf(buf, "\n");
++ return buf - buffer;
++}
++
++const struct instr_info instructions[] =
++{
++ { D3DSIO_NOP, "nop", 0, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_MOV, "mov", 2, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_ADD, "add", 3, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_SUB, "sub", 3, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_MAD, "mad", 4, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_MUL, "mul", 3, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_RCP, "rcp", 2, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_RSQ, "rsq", 2, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_DP3, "dp3", 3, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_DP4, "dp4", 3, instr_generic, 0x0100, 0xFFFF
}, /* >= 1.2 for PS */
++ { D3DSIO_MIN, "min", 3, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_MAX, "max", 3, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_SLT, "slt", 3, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_SGE, "sge", 3, instr_generic, 0x0100, 0xFFFF
}, /* VS only */
++ { D3DSIO_EXP, "exp", 2, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_LOG, "log", 2, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_LIT, "lit", 2, instr_generic, 0x0100, 0xFFFF
}, /* VS only */
++ { D3DSIO_DST, "dst", 3, instr_generic, 0x0100, 0xFFFF
}, /* VS only */
++ { D3DSIO_LRP, "lrp", 4, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for VS */
++ { D3DSIO_FRC, "frc", 2, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_M4x4, "m4x4", 3, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_M4x3, "m4x3", 3, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_M3x4, "m3x4", 3, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_M3x3, "m3x3", 3, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_M3x2, "m3x2", 3, instr_generic, 0x0100, 0xFFFF
}, /* >= 2.0 for PS */
++ { D3DSIO_CALL, "call", 1, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_CALLNZ, "callnz", 2, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_LOOP, "loop", 2, instr_generic, 0x0200, 0xFFFF
}, /* >= 3.0 for PS */
++ { D3DSIO_RET, "ret", 0, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_ENDLOOP, "endloop", 1, instr_generic, 0x0200, 0xFFFF
}, /* >= 3.0 for PS */
++ { D3DSIO_LABEL, "label", 1, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_DCL, "dcl", 1, instr_dcl, 0x0100, 0xFFFF
},
++ { D3DSIO_POW, "pow", 3, instr_generic, 0x0200, 0xFFFF
},
++ { D3DSIO_CRS, "crs", 3, instr_generic, 0x0200, 0xFFFF
},
++ { D3DSIO_SGN, "sgn", 4, instr_generic, 0x0200, 0xFFFF
}, /* VS only */
++ { D3DSIO_ABS, "abs", 2, instr_generic, 0x0200, 0xFFFF
},
++ { D3DSIO_NRM, "nrm", 2, instr_generic, 0x0200, 0xFFFF
},
++ { D3DSIO_SINCOS, "sincos", 4, instr_generic, 0x0200, 0x02FF
},
++ { D3DSIO_SINCOS, "sincos", 2, instr_generic, 0x0300, 0xFFFF
},
++ { D3DSIO_REP, "rep", 1, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_ENDREP, "endrep", 0, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_IF, "if", 1, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_IFC, "if_comp", 2, instr_generic, 0x0200, 0xFFFF
},
++ { D3DSIO_ELSE, "else", 0, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_ENDIF, "endif", 0, instr_generic, 0x0200, 0xFFFF
}, /* >= 2.a for PS */
++ { D3DSIO_BREAK, "break", 0, instr_generic, 0x0201, 0xFFFF
},
++ { D3DSIO_BREAKC, "break_comp", 2, instr_generic, 0x0201, 0xFFFF
},
++ { D3DSIO_MOVA, "mova", 2, instr_generic, 0x0200, 0xFFFF
}, /* VS only */
++ { D3DSIO_DEFB, "defb", 2, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_DEFI, "defi", 2, instr_generic, 0x0100, 0xFFFF
},
++ { D3DSIO_TEXCOORD, "texcoord", 1, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXCOORD, "texcrd", 2, instr_generic, 0x0104, 0x0104
}, /* PS only */
++ { D3DSIO_TEXKILL, "texkill", 1, instr_generic, 0x0100, 0xFFFF
}, /* PS only */
++ { D3DSIO_TEX, "tex", 1, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEX, "texld", 2, instr_generic, 0x0104, 0x0104
}, /* PS only */
++ { D3DSIO_TEX, "texld", 3, instr_generic, 0x0200, 0xFFFF
}, /* PS only */
++ { D3DSIO_TEXBEM, "texbem", 2, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXBEML, "texbeml", 2, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXREG2AR, "texreg2ar", 2, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXREG2GB, "texreg2gb", 2, instr_generic, 0x0102, 0x0103
}, /* PS only */
++ { D3DSIO_TEXM3x2PAD, "texm3x2pad", 2, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXM3x2TEX, "texm3x2tex", 2, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXM3x3PAD, "texm3x3pad", 2, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXM3x3TEX, "texm3x3tex", 2, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXM3x3DIFF, "texm3x3diff", 2, instr_generic, 0x0100, 0xFFFF
}, /* PS only - Not documented */
++ { D3DSIO_TEXM3x3SPEC, "texm3x3spec", 3, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_TEXM3x3VSPEC, "texm3x3vspec", 2, instr_generic, 0x0100, 0x0103
}, /* PS only */
++ { D3DSIO_EXPP, "expp", 2, instr_generic, 0x0100, 0xFFFF
}, /* VS only */
++ { D3DSIO_LOGP, "logp", 2, instr_generic, 0x0100, 0xFFFF
}, /* VS only */
++ { D3DSIO_CND, "cnd", 4, instr_generic, 0x0100, 0x0104
}, /* PS only */
++ { D3DSIO_DEF, "def", 5, instr_def, 0x0100, 0xFFFF
},
++ { D3DSIO_TEXREG2RGB, "texreg2rgb", 2, instr_generic, 0x0102, 0x0103
}, /* PS only */
++ { D3DSIO_TEXDP3TEX, "texdp3tex", 2, instr_generic, 0x0102, 0x0103
}, /* PS only */
++ { D3DSIO_TEXM3x2DEPTH, "texm3x2depth", 2, instr_generic, 0x0103, 0x0103
}, /* PS only */
++ { D3DSIO_TEXDP3, "texdp3", 2, instr_generic, 0x0102, 0x0103
}, /* PS only */
++ { D3DSIO_TEXM3x3, "texm3x3", 2, instr_generic, 0x0102, 0x0103
}, /* PS only */
++ { D3DSIO_TEXDEPTH, "texdepth", 1, instr_generic, 0x0104, 0x0104
}, /* PS only */
++ { D3DSIO_CMP, "cmp", 4, instr_generic, 0x0102, 0xFFFF
}, /* PS only */
++ { D3DSIO_BEM, "bem", 3, instr_generic, 0x0104, 0x0104
}, /* PS only */
++ { D3DSIO_DP2ADD, "dp2add", 4, instr_generic, 0x0200, 0xFFFF
}, /* PS only */
++ { D3DSIO_DSX, "dsx", 2, instr_generic, 0x0201, 0xFFFF
}, /* PS only */
++ { D3DSIO_DSY, "dsy", 2, instr_generic, 0x0201, 0xFFFF
}, /* PS only */
++ { D3DSIO_TEXLDD, "texldd", 5, instr_generic, 0x0201, 0xFFFF
}, /* PS only - not existing for 2.b */
++ { D3DSIO_SETP, "setp_comp", 3, instr_generic, 0x0201, 0xFFFF
},
++ { D3DSIO_TEXLDL, "texldl", 3, instr_generic, 0x0300, 0xFFFF
},
++ { D3DSIO_BREAKP, "breakp", 1, instr_generic, 0x0201, 0xFFFF
},
++ { D3DSIO_PHASE, "phase", 0, instr_generic, 0x0104, 0x0104
}, /* PS only */
++ { D3DSIO_COMMENT, "", 0, instr_comment, 0x0100, 0xFFFF
}
++};
++
+ HRESULT WINAPI D3DXDisassembleShader(const DWORD *shader, BOOL colorcode, const char
*comments, ID3DXBuffer **disassembly)
+ {
+- FIXME("%p %d %s %p: stub\n", shader, colorcode, debugstr_a(comments),
disassembly);
+- return E_OUTOFMEMORY;
++ DWORD *ptr = (DWORD *)shader;
++ char *buffer, *buf;
++ UINT capacity = 4096;
++ BOOL ps;
++ WORD version;
++ HRESULT hr;
++
++ TRACE("%p %d %s %p\n", shader, colorcode, debugstr_a(comments),
disassembly);
++
++ if (!shader || !disassembly)
++ return D3DERR_INVALIDCALL;
++
++ buf = buffer = HeapAlloc(GetProcessHeap(), 0, capacity);
++ if (!buffer)
++ return E_OUTOFMEMORY;
++
++ ps = (*ptr >> 16) & 1;
++ version = *ptr & 0xFFFF;
++ buf += sprintf(buf, " %s_%d_%d\n", ps ? "ps" :
"vs", D3DSHADER_VERSION_MAJOR(*ptr), D3DSHADER_VERSION_MINOR(*ptr));
++ ptr++;
++
++ while (*ptr != D3DSIO_END)
++ {
++ DWORD index;
++
++ if ((buf - buffer + 128) > capacity)
++ {
++ UINT count = buf - buffer;
++ char *new_buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, capacity * 2);
++ if (!new_buffer)
++ {
++ HeapFree(GetProcessHeap(), 0, buffer);
++ return E_OUTOFMEMORY;
++ }
++ capacity *= 2;
++ buffer = new_buffer;
++ buf = buffer + count;
++ }
++
++ for (index = 0; index < sizeof(instructions)/sizeof(instructions[0]);
index++)
++ if (((*ptr & D3DSI_OPCODE_MASK) == instructions[index].opcode)
&&
++ (version >= instructions[index].min_version) && (version
<= instructions[index].max_version))
++ break;
++
++ if (index != sizeof(instructions)/sizeof(instructions[0]))
++ {
++ buf += instructions[index].function(&(instructions[index]), &ptr,
buf, ps);
++ }
++ else
++ {
++ buf += sprintf(buf, " ??? (Unknown opcode %x)\n", *ptr);
++ while (*++ptr & (1u << 31));
++ }
++ }
++
++ hr = D3DXCreateBuffer(buf - buffer + 1 , disassembly);
++ if (SUCCEEDED(hr))
++ strcpy(ID3DXBuffer_GetBufferPointer(*disassembly), buffer);
++ HeapFree(GetProcessHeap(), 0, buffer);
++
++ return hr;
+ }
+
+ struct d3dx9_texture_shader