diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 6ea5e9d057d..abf5019fe22 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -85,6 +85,29 @@ const SHADER_OPCODE* shader_get_opcode( return NULL; } +/* Read a parameter opcode from the input stream, + * and possibly a relative addressing token. + * Return the number of tokens read */ +int shader_get_param( + IWineD3DBaseShader* iface, + const DWORD* pToken, + DWORD* param, + DWORD* addr_token) { + + /* PS >= 3.0 have relative addressing (with token) + * VS >= 2.0 have relative addressing (with token) + * VS >= 1.0 < 2.0 have relative addressing (without token) + * The version check below should work in general */ + + IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; + char rel_token = D3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2 && + ((*pToken & D3DSHADER_ADDRESSMODE_MASK) == D3DSHADER_ADDRMODE_RELATIVE); + + *param = *pToken; + *addr_token = rel_token? *(pToken + 1): 0; + return rel_token? 2:1; +} + /* Return the number of parameters to skip for an opcode */ static inline int shader_skip_opcode( IWineD3DBaseShaderImpl* This, @@ -99,6 +122,36 @@ static inline int shader_skip_opcode( curOpcode->num_params; } +/* Read the parameters of an unrecognized opcode from the input stream + * Return the number of tokens read. + * + * Note: This function assumes source or destination token format. + * It will not work with specially-formatted tokens like DEF or DCL, + * but hopefully those would be recognized */ + +int shader_skip_unrecognized( + IWineD3DBaseShader* iface, + const DWORD* pToken) { + + int tokens_read = 0; + int i = 0; + + /* TODO: Think of a good name for 0x80000000 and replace it with a constant */ + while (*pToken & 0x80000000) { + + DWORD param, addr_token; + tokens_read += shader_get_param(iface, pToken, ¶m, &addr_token); + pToken += tokens_read; + + FIXME("Unrecognized opcode param: token=%08lX " + "addr_token=%08lX name=", param, addr_token); + shader_dump_param(iface, param, i); + FIXME("\n"); + ++i; + } + return tokens_read; +} + /* Note: For vertex shaders, * texUsed = addrUsed, and * D3DSPR_TEXTURE = D3DSPR_ADDR. @@ -484,11 +537,9 @@ void generate_base_shader( curOpcode = shader_get_opcode(iface, opcode_token); /* Unknown opcode and its parameters */ - if (NULL == curOpcode) { - while (*pToken & 0x80000000) { /* TODO: Think of a sensible name for 0x80000000 */ - FIXME("unrecognized opcode: %08lx\n", *pToken); - ++pToken; - } + if (NULL == curOpcode) { + FIXME("Unrecognized opcode: token=%08lX\n", opcode_token); + pToken += shader_skip_unrecognized(iface, pToken); /* Using GLSL & no generator function exists */ } else if (USING_GLSL && curOpcode->hw_glsl_fct == NULL) { diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 99c1fc9632b..4c109e24c50 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -1376,6 +1376,7 @@ HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, C IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface; const DWORD* pToken = pFunction; const SHADER_OPCODE *curOpcode = NULL; + DWORD opcode_token; DWORD len = 0; DWORD i; TRACE("(%p) : Parsing programme\n", This); @@ -1399,20 +1400,16 @@ HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *iface, C if (!This->baseShader.version) { WARN("(%p) : pixel shader doesn't have a valid version identifier\n", This); } - curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken); - ++pToken; - ++len; + opcode_token = *pToken++; + curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token); + len++; if (NULL == curOpcode) { + int tokens_read; - /* TODO: Think of a good name for 0x80000000 and replace it with a constant */ - while (*pToken & 0x80000000) { - - /* unknown current opcode ... */ - TRACE("unrecognized opcode: %08lx", *pToken); - ++pToken; - ++len; - TRACE("\n"); - } + FIXME("Unrecognized opcode: token=%08lX\n", opcode_token); + tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken); + pToken += tokens_read; + len += tokens_read; } else { if (curOpcode->opcode == D3DSIO_DCL) { diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c index 4c8eb14f354..fc68c71ea8f 100644 --- a/dlls/wined3d/vertexshader.c +++ b/dlls/wined3d/vertexshader.c @@ -1116,7 +1116,8 @@ BOOL IWineD3DVertexShaderImpl_ExecuteHAL(IWineD3DVertexShader* iface, WINEVSHADE HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, WINEVSHADERINPUTDATA* input, WINEVSHADEROUTPUTDATA* output) { IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface; - + DWORD opcode_token; + /** Vertex Shader Temporary Registers */ WINED3DSHADERVECTOR R[12]; /*D3DSHADERSCALAR A0;*/ @@ -1175,23 +1176,15 @@ HRESULT WINAPI IWineD3DVertexShaderImpl_ExecuteSW(IWineD3DVertexShader* iface, W pToken += comment_len; continue ; } - curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken); - ++pToken; + + opcode_token = *pToken++; + curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token); + if (NULL == curOpcode) { - i = 0; - /* unknown current opcode ... */ - /* TODO: Think of a name for 0x80000000 and replace its use with a constant */ - while (*pToken & 0x80000000) { - if (i == 0) { - FIXME("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - This->baseShader.function, *(pToken - 1)); - } - FIXME("unrecognized opcode param: pos=%d token=%08lX what=", pToken - This->baseShader.function, *pToken); - shader_dump_param((IWineD3DBaseShader*) This, *pToken, i); - TRACE("\n"); - ++i; - ++pToken; - } + FIXME("Unrecognized opcode: token=%08lX\n", opcode_token); + pToken += shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken); /* return FALSE; */ + } else { if (curOpcode->num_params > 0) { /* TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken); */ @@ -1505,6 +1498,7 @@ HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, IWineD3DVertexShaderImpl *This =(IWineD3DVertexShaderImpl *)iface; const DWORD* pToken = pFunction; const SHADER_OPCODE* curOpcode = NULL; + DWORD opcode_token; DWORD len = 0; DWORD i; TRACE("(%p) : Parsing programme\n", This); @@ -1531,18 +1525,18 @@ HRESULT WINAPI IWineD3DVertexShaderImpl_SetFunction(IWineD3DVertexShader *iface, len += comment_len + 1; continue; } - curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken); - ++pToken; - ++len; + + opcode_token = *pToken++; + curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, opcode_token); + len++; + if (NULL == curOpcode) { - /* TODO: Think of a good name for 0x80000000 and replace it with a constant */ - while (*pToken & 0x80000000) { - /* unknown current opcode ... */ - FIXME("unrecognized opcode: %08lx", *pToken); - ++pToken; - ++len; - TRACE("\n"); - } + int tokens_read; + + FIXME("Unrecognized opcode: token=%08lX\n", opcode_token); + tokens_read = shader_skip_unrecognized((IWineD3DBaseShader*) This, pToken); + pToken += tokens_read; + len += tokens_read; } else { if (curOpcode->opcode == D3DSIO_DCL) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index aa875e6373c..34d512e00ec 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1372,6 +1372,16 @@ extern void shader_dump_param( const DWORD param, int input); +extern int shader_get_param( + IWineD3DBaseShader* iface, + const DWORD* pToken, + DWORD* param, + DWORD* addr_token); + +extern int shader_skip_unrecognized( + IWineD3DBaseShader* iface, + const DWORD* pToken); + inline static int shader_get_regtype(const DWORD param) { return (((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) | ((param & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2));