https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e5c42da45cb306ee8294de6074927c05c8b6dac4

commit e5c42da45cb306ee8294de6074927c05c8b6dac4
Author:     Amine Khaldi <[email protected]>
AuthorDate: Thu Mar 8 13:26:47 2018 +0100
Commit:     Amine Khaldi <[email protected]>
CommitDate: Thu Mar 8 13:26:47 2018 +0100

    [D3DX9_*] Sync with Wine Staging 3.3. CORE-14434
---
 dll/directx/wine/d3dx9_36/CMakeLists.txt           |   8 +-
 dll/directx/wine/d3dx9_36/animation.c              |  21 +-
 dll/directx/wine/d3dx9_36/core.c                   |   7 +-
 dll/directx/wine/d3dx9_36/d3dx9_36.spec            |   8 +-
 .../{d3dx9_36_private.h => d3dx9_private.h}        |  31 +-
 dll/directx/wine/d3dx9_36/effect.c                 |  57 +++-
 dll/directx/wine/d3dx9_36/font.c                   | 254 ++++++++++++--
 dll/directx/wine/d3dx9_36/line.c                   |   7 +-
 .../wine/d3dx9_36/{d3dx9_36_main.c => main.c}      |  28 +-
 dll/directx/wine/d3dx9_36/math.c                   |  41 ++-
 dll/directx/wine/d3dx9_36/mesh.c                   |  83 ++++-
 dll/directx/wine/d3dx9_36/precomp.h                |  28 ++
 dll/directx/wine/d3dx9_36/preshader.c              |  10 +-
 dll/directx/wine/d3dx9_36/render.c                 |   7 +-
 dll/directx/wine/d3dx9_36/shader.c                 | 372 ++++++++++++++++++++-
 dll/directx/wine/d3dx9_36/skin.c                   | 115 ++++++-
 dll/directx/wine/d3dx9_36/sprite.c                 |   7 +-
 dll/directx/wine/d3dx9_36/surface.c                | 229 ++++++++++++-
 dll/directx/wine/d3dx9_36/texture.c                |  24 +-
 dll/directx/wine/d3dx9_36/util.c                   |  10 +-
 dll/directx/wine/d3dx9_36/volume.c                 |   7 +-
 dll/directx/wine/d3dx9_36/xfile.c                  |  10 +-
 media/doc/README.WINE                              |   2 +-
 23 files changed, 1218 insertions(+), 148 deletions(-)

diff --git a/dll/directx/wine/d3dx9_36/CMakeLists.txt 
b/dll/directx/wine/d3dx9_36/CMakeLists.txt
index 1b56e547d4..836ee9c743 100644
--- a/dll/directx/wine/d3dx9_36/CMakeLists.txt
+++ b/dll/directx/wine/d3dx9_36/CMakeLists.txt
@@ -1,15 +1,15 @@
 
-add_definitions(-D__WINESRC__ -Dcopysignf=_copysignf -D_D3DX9_VER=36)
+add_definitions(-D__WINESRC__ -Dcopysignf=_copysignf -DD3DX_SDK_VERSION=36 
-D_D3DX9_VER=36)
 include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
 spec2def(d3dx9_36.dll d3dx9_36.spec ADD_IMPORTLIB)
 
 list(APPEND SOURCE
     animation.c
     core.c
-    d3dx9_36_main.c
     effect.c
     font.c
     line.c
+    main.c
     math.c
     mesh.c
     preshader.c
@@ -22,7 +22,7 @@ list(APPEND SOURCE
     util.c
     volume.c
     xfile.c
-    d3dx9_36_private.h)
+    precomp.h)
 
 add_library(d3dx9_36 SHARED
     ${SOURCE}
@@ -35,5 +35,5 @@ set_module_type(d3dx9_36 win32dll)
 add_dependencies(d3dx9_36 d3d_idl_headers)
 target_link_libraries(d3dx9_36 dxguid wine)
 add_importlibs(d3dx9_36 d3dcompiler_43 d3dxof d3dwine user32 ole32 gdi32 
msvcrt kernel32 ntdll)
-add_pch(d3dx9_36 d3dx9_36_private.h SOURCE)
+add_pch(d3dx9_36 precomp.h SOURCE)
 add_cd_file(TARGET d3dx9_36 DESTINATION reactos/system32 FOR all)
diff --git a/dll/directx/wine/d3dx9_36/animation.c 
b/dll/directx/wine/d3dx9_36/animation.c
index e1e895f630..6be2dd6b5a 100644
--- a/dll/directx/wine/d3dx9_36/animation.c
+++ b/dll/directx/wine/d3dx9_36/animation.c
@@ -18,7 +18,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 struct d3dx9_animation_controller
 {
@@ -392,7 +397,7 @@ static HRESULT WINAPI 
d3dx9_animation_controller_CloneAnimationController(ID3DXA
     return E_NOTIMPL;
 }
 
-static /* const */ struct ID3DXAnimationControllerVtbl 
d3dx9_animation_controller_vtbl =
+static const struct ID3DXAnimationControllerVtbl 
d3dx9_animation_controller_vtbl =
 {
     d3dx9_animation_controller_QueryInterface,
     d3dx9_animation_controller_AddRef,
@@ -464,3 +469,15 @@ HRESULT WINAPI D3DXCreateAnimationController(UINT 
max_outputs, UINT max_sets,
 
     return D3D_OK;
 }
+
+HRESULT WINAPI D3DXCreateKeyframedAnimationSet(const char *name, double 
ticks_per_second,
+        D3DXPLAYBACK_TYPE playback_type, UINT animation_count, UINT 
callback_key_count,
+        const D3DXKEY_CALLBACK *callback_keys, ID3DXKeyframedAnimationSet 
**animation_set)
+{
+    FIXME("name %s, ticks_per_second %.16e, playback_type %u, animation_count 
%u, "
+            "callback_key_count %u, callback_keys %p, animation_set %p 
stub.\n",
+            debugstr_a(name), ticks_per_second, playback_type, animation_count,
+            callback_key_count, callback_keys, animation_set);
+
+    return E_NOTIMPL;
+}
diff --git a/dll/directx/wine/d3dx9_36/core.c b/dll/directx/wine/d3dx9_36/core.c
index e7624f2a21..1eb289ece6 100644
--- a/dll/directx/wine/d3dx9_36/core.c
+++ b/dll/directx/wine/d3dx9_36/core.c
@@ -17,7 +17,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 struct ID3DXBufferImpl
 {
diff --git a/dll/directx/wine/d3dx9_36/d3dx9_36.spec 
b/dll/directx/wine/d3dx9_36/d3dx9_36.spec
index e487aa12ec..1e035f76c1 100644
--- a/dll/directx/wine/d3dx9_36/d3dx9_36.spec
+++ b/dll/directx/wine/d3dx9_36/d3dx9_36.spec
@@ -22,9 +22,9 @@
 @ stdcall -stub D3DXComputeIMTFromPerVertexSignal(ptr ptr long long long ptr 
ptr ptr)
 @ stdcall -stub D3DXComputeIMTFromSignal(ptr long long long long ptr ptr ptr 
ptr ptr)
 @ stdcall -stub D3DXComputeIMTFromTexture(ptr ptr long long ptr ptr ptr)
-@ stdcall -stub D3DXComputeNormalMap(ptr ptr ptr long long float)
+@ stdcall D3DXComputeNormalMap(ptr ptr ptr long long float)
 @ stdcall D3DXComputeNormals(ptr ptr)
-@ stdcall -stub D3DXComputeTangent(ptr long long long long ptr)
+@ stdcall D3DXComputeTangent(ptr long long long long ptr)
 @ stdcall -stub D3DXComputeTangentFrame(ptr long)
 @ stdcall D3DXComputeTangentFrameEx(ptr long long long long long long long 
long long ptr float float float ptr ptr)
 @ stdcall -stub D3DXConcatenateMeshes(ptr long long ptr ptr ptr ptr ptr)
@@ -68,7 +68,7 @@
 @ stdcall D3DXCreateFontW(ptr long long long long long long long long long 
wstr ptr)
 @ stdcall D3DXCreateFragmentLinker(ptr long ptr)
 @ stdcall D3DXCreateFragmentLinkerEx(ptr long long ptr)
-@ stdcall -stub D3DXCreateKeyframedAnimationSet(ptr long long long long ptr 
ptr)
+@ stdcall D3DXCreateKeyframedAnimationSet(str double long long long ptr ptr)
 @ stdcall D3DXCreateLine(ptr ptr)
 @ stdcall D3DXCreateMatrixStack(long ptr)
 @ stdcall D3DXCreateMesh(long long long ptr ptr ptr)
@@ -229,7 +229,7 @@
 @ stdcall D3DXMatrixTranslation(ptr float float float)
 @ stdcall D3DXMatrixTranspose(ptr ptr)
 @ stdcall D3DXOptimizeFaces(ptr long long long ptr)
-@ stdcall -stub D3DXOptimizeVertices(ptr long long long ptr)
+@ stdcall D3DXOptimizeVertices(ptr long long long ptr)
 @ stdcall D3DXPlaneFromPointNormal(ptr ptr ptr)
 @ stdcall D3DXPlaneFromPoints(ptr ptr ptr ptr)
 @ stdcall D3DXPlaneIntersectLine(ptr ptr ptr ptr)
diff --git a/dll/directx/wine/d3dx9_36/d3dx9_36_private.h 
b/dll/directx/wine/d3dx9_36/d3dx9_private.h
similarity index 96%
rename from dll/directx/wine/d3dx9_36/d3dx9_36_private.h
rename to dll/directx/wine/d3dx9_36/d3dx9_private.h
index ddc38225e0..edb7455a5f 100644
--- a/dll/directx/wine/d3dx9_36/d3dx9_36_private.h
+++ b/dll/directx/wine/d3dx9_36/d3dx9_private.h
@@ -19,33 +19,14 @@
  *
  */
 
-#ifndef __WINE_D3DX9_36_PRIVATE_H
-#define __WINE_D3DX9_36_PRIVATE_H
+#ifndef __WINE_D3DX9_PRIVATE_H
+#define __WINE_D3DX9_PRIVATE_H
 
-#include <config.h>
-#include <wine/port.h>
-
-#include <assert.h>
-#include <stdarg.h>
-
-#define WIN32_NO_STATUS
-#define _INC_WINDOWS
-#define COM_NO_WINDOWS_H
-
-#define COBJMACROS
 #define NONAMELESSUNION
-#define NONAMELESSSTRUCT
+#include "wine/debug.h"
 
-#include <windef.h>
-#include <winbase.h>
-#include <wingdi.h>
-#include <winuser.h>
-#include <d3dx9.h>
-
-#include <wine/unicode.h>
-
-#include <wine/debug.h>
-WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+#define COBJMACROS
+#include "d3dx9.h"
 
 #define ULONG64_MAX (~(ULONG64)0)
 
@@ -409,4 +390,4 @@ const struct ctab_constant 
*d3dx_shader_get_ctab_constant(ID3DXConstantTable *if
 
 HRESULT create_dummy_skin(ID3DXSkinInfo **iface) DECLSPEC_HIDDEN;
 
-#endif /* __WINE_D3DX9_36_PRIVATE_H */
+#endif /* __WINE_D3DX9_PRIVATE_H */
diff --git a/dll/directx/wine/d3dx9_36/effect.c 
b/dll/directx/wine/d3dx9_36/effect.c
index 7a5975a706..e2c0ce3728 100644
--- a/dll/directx/wine/d3dx9_36/effect.c
+++ b/dll/directx/wine/d3dx9_36/effect.c
@@ -17,9 +17,11 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
 
-#include <d3dcompiler.h>
+#include "d3dx9_private.h"
+#include "d3dcompiler.h"
 
 /* Constants for special INT/FLOAT conversation */
 #define INT_FLOAT_MULTI 255.0f
@@ -31,6 +33,8 @@ static const char parameter_magic_string[4] = {'@', '!', '#', 
'\xFF'};
 
 #define INITIAL_POOL_SIZE 16
 
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+
 enum STATE_CLASS
 {
     SC_LIGHTENABLE,
@@ -3980,13 +3984,41 @@ done:
     return ret;
 }
 
-static HRESULT WINAPI ID3DXEffectImpl_FindNextValidTechnique(ID3DXEffect* 
iface, D3DXHANDLE technique, D3DXHANDLE* next_technique)
+static HRESULT WINAPI ID3DXEffectImpl_FindNextValidTechnique(ID3DXEffect 
*iface,
+        D3DXHANDLE technique, D3DXHANDLE *next_technique)
 {
     struct ID3DXEffectImpl *This = impl_from_ID3DXEffect(iface);
+    struct d3dx9_base_effect *base_effect = &This->base_effect;
+    UINT i = 0;
 
-    FIXME("(%p)->(%p, %p): stub\n", This, technique, next_technique);
+    TRACE("iface %p, technique %p, next_technique %p\n", iface, technique, 
next_technique);
 
-    return E_NOTIMPL;
+    if (!next_technique)
+        return D3DERR_INVALIDCALL;
+
+    if (technique)
+    {
+        for (; i < base_effect->technique_count; i++)
+        {
+            if (technique == get_technique_handle(&base_effect->techniques[i]))
+            {
+                i++; /* Go to next technique */
+                break;
+            }
+        }
+    }
+
+    for (; i < base_effect->technique_count; i++)
+    {
+        if (SUCCEEDED(iface->lpVtbl->ValidateTechnique(iface, 
get_technique_handle(&base_effect->techniques[i]))))
+        {
+            *next_technique = 
get_technique_handle(&base_effect->techniques[i]);
+            return D3D_OK;
+        }
+    }
+
+    *next_technique = NULL;
+    return S_FALSE;
 }
 
 static BOOL walk_parameter_dep(struct d3dx_parameter *param, 
walk_parameter_dep_func param_func,
@@ -4347,6 +4379,7 @@ static HRESULT WINAPI 
ID3DXEffectImpl_ApplyParameterBlock(ID3DXEffect* iface, D3
     return E_NOTIMPL;
 }
 
+#if _D3DX9_VER >= 26
 static HRESULT WINAPI ID3DXEffectImpl_DeleteParameterBlock(ID3DXEffect* iface, 
D3DXHANDLE parameter_block)
 {
     struct ID3DXEffectImpl *This = impl_from_ID3DXEffect(iface);
@@ -4355,6 +4388,7 @@ static HRESULT WINAPI 
ID3DXEffectImpl_DeleteParameterBlock(ID3DXEffect* iface, D
 
     return E_NOTIMPL;
 }
+#endif
 
 static HRESULT WINAPI ID3DXEffectImpl_CloneEffect(ID3DXEffect *iface,
         struct IDirect3DDevice9 *device, struct ID3DXEffect **effect)
@@ -4363,9 +4397,15 @@ static HRESULT WINAPI 
ID3DXEffectImpl_CloneEffect(ID3DXEffect *iface,
 
     FIXME("(%p)->(%p, %p): stub\n", This, device, effect);
 
-    return E_NOTIMPL;
+    if (!effect)
+        return D3DXERR_INVALIDDATA;
+
+    iface->lpVtbl->AddRef(iface);
+    *effect = iface;
+    return S_OK;
 }
 
+#if _D3DX9_VER >= 27
 static HRESULT WINAPI ID3DXEffectImpl_SetRawValue(ID3DXEffect *iface,
         D3DXHANDLE parameter, const void *data, UINT byte_offset, UINT bytes)
 {
@@ -4374,6 +4414,7 @@ static HRESULT WINAPI 
ID3DXEffectImpl_SetRawValue(ID3DXEffect *iface,
 
     return E_NOTIMPL;
 }
+#endif
 
 static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl =
 {
@@ -4456,9 +4497,13 @@ static const struct ID3DXEffectVtbl ID3DXEffect_Vtbl =
     ID3DXEffectImpl_BeginParameterBlock,
     ID3DXEffectImpl_EndParameterBlock,
     ID3DXEffectImpl_ApplyParameterBlock,
+#if _D3DX9_VER >= 26
     ID3DXEffectImpl_DeleteParameterBlock,
+#endif
     ID3DXEffectImpl_CloneEffect,
+#if _D3DX9_VER >= 27
     ID3DXEffectImpl_SetRawValue
+#endif
 };
 
 static inline struct ID3DXEffectCompilerImpl 
*impl_from_ID3DXEffectCompiler(ID3DXEffectCompiler *iface)
diff --git a/dll/directx/wine/d3dx9_36/font.c b/dll/directx/wine/d3dx9_36/font.c
index 575e80d0bb..b4b9600320 100644
--- a/dll/directx/wine/d3dx9_36/font.c
+++ b/dll/directx/wine/d3dx9_36/font.c
@@ -17,7 +17,13 @@
  *
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+#include "wine/unicode.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 struct d3dx_font
 {
@@ -29,8 +35,29 @@ struct d3dx_font
 
     HDC hdc;
     HFONT hfont;
+
+    UINT tex_width;
+    UINT tex_height;
+    IDirect3DTexture9 *texture;
+    HBITMAP bitmap;
+    BYTE *bits;
 };
 
+/* Returns the smallest power of 2 which is greater than or equal to num */
+static UINT make_pow2(UINT num)
+{
+    UINT result = 1;
+
+    /* In the unlikely event somebody passes a large value, make sure we don't 
enter an infinite loop */
+    if (num >= 0x80000000)
+        return 0x80000000;
+
+    while (result < num)
+        result <<= 1;
+
+    return result;
+}
+
 static inline struct d3dx_font *impl_from_ID3DXFont(ID3DXFont *iface)
 {
     return CONTAINING_RECORD(iface, struct d3dx_font, ID3DXFont_iface);
@@ -57,19 +84,27 @@ static HRESULT WINAPI 
ID3DXFontImpl_QueryInterface(ID3DXFont *iface, REFIID riid
 static ULONG WINAPI ID3DXFontImpl_AddRef(ID3DXFont *iface)
 {
     struct d3dx_font *This = impl_from_ID3DXFont(iface);
-    ULONG ref=InterlockedIncrement(&This->ref);
+    ULONG ref = InterlockedIncrement(&This->ref);
+
     TRACE("%p increasing refcount to %u\n", iface, ref);
+
     return ref;
 }
 
 static ULONG WINAPI ID3DXFontImpl_Release(ID3DXFont *iface)
 {
     struct d3dx_font *This = impl_from_ID3DXFont(iface);
-    ULONG ref=InterlockedDecrement(&This->ref);
+    ULONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("%p decreasing refcount to %u\n", iface, ref);
 
-    if(ref==0) {
+    if (!ref)
+    {
+        if (This->texture)
+        {
+            IDirect3DTexture9_Release(This->texture);
+            DeleteObject(This->bitmap);
+        }
         DeleteObject(This->hfont);
         DeleteDC(This->hdc);
         IDirect3DDevice9_Release(This->device);
@@ -172,17 +207,187 @@ static HRESULT WINAPI 
ID3DXFontImpl_PreloadTextW(ID3DXFont *iface, const WCHAR *
 static INT WINAPI ID3DXFontImpl_DrawTextA(ID3DXFont *iface, ID3DXSprite 
*sprite,
         const char *string, INT count, RECT *rect, DWORD format, D3DCOLOR 
color)
 {
-    FIXME("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, 
color 0x%08x stub!\n",
+    LPWSTR stringW;
+    INT countW, ret = 0;
+
+    TRACE("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, 
color 0x%08x\n",
             iface,  sprite, debugstr_a(string), count, wine_dbgstr_rect(rect), 
format, color);
-    return 1;
+
+    if (!string || count == 0)
+        return 0;
+
+    if (count < 0)
+       count = -1;
+
+    countW = MultiByteToWideChar(CP_ACP, 0, string, count, NULL, 0);
+    stringW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR));
+    if (stringW)
+    {
+        MultiByteToWideChar(CP_ACP, 0, string, count, stringW, countW);
+        ret = ID3DXFont_DrawTextW(iface, sprite, stringW, countW, rect, 
format, color);
+        HeapFree(GetProcessHeap(), 0, stringW);
+    }
+
+    return ret;
 }
 
 static INT WINAPI ID3DXFontImpl_DrawTextW(ID3DXFont *iface, ID3DXSprite 
*sprite,
         const WCHAR *string, INT count, RECT *rect, DWORD format, D3DCOLOR 
color)
 {
-    FIXME("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, 
color 0x%08x stub!\n",
+    struct d3dx_font *This = impl_from_ID3DXFont(iface);
+    RECT calc_rect;
+    INT height;
+
+    TRACE("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, 
color 0x%08x\n",
             iface,  sprite, debugstr_w(string), count, wine_dbgstr_rect(rect), 
format, color);
-    return 1;
+
+    if (!string || count == 0)
+        return 0;
+
+    if (count < 0)
+       count = lstrlenW(string);
+
+    /* Strip terminating NULL characters */
+    while (count > 0 && !string[count-1])
+        count--;
+
+    if (rect)
+        calc_rect = *rect;
+
+    height = DrawTextW(This->hdc, string, count, &calc_rect, format | 
DT_CALCRECT);
+
+    if (format & DT_CALCRECT)
+    {
+        if (rect)
+            *rect = calc_rect;
+        return height;
+    }
+
+    if (format & DT_CENTER)
+    {
+        UINT new_width = calc_rect.right - calc_rect.left;
+        calc_rect.left = (rect->right + rect->left - new_width) / 2;
+        calc_rect.right = calc_rect.left + new_width;
+    }
+
+    if (height && (calc_rect.left < calc_rect.right))
+    {
+        D3DLOCKED_RECT locked_rect;
+        D3DXVECTOR3 position;
+        UINT text_width, text_height;
+        RECT text_rect;
+        ID3DXSprite *target = sprite;
+        HRESULT hr;
+        int i, j;
+
+        /* Get rect position and dimensions */
+        position.x = calc_rect.left;
+        position.y = calc_rect.top;
+        position.z = 0;
+        text_width = calc_rect.right - calc_rect.left;
+        text_height = calc_rect.bottom - calc_rect.top;
+        text_rect.left = 0;
+        text_rect.top = 0;
+        text_rect.right = text_width;
+        text_rect.bottom = text_height;
+
+        /* We need to flush as it seems all draws in the begin/end sequence 
use only the latest updated texture */
+        if (sprite)
+            ID3DXSprite_Flush(sprite);
+
+        /* Extend texture and DIB section to contain text */
+        if ((text_width > This->tex_width) || (text_height > This->tex_height))
+        {
+            BITMAPINFOHEADER header;
+
+            if (text_width > This->tex_width)
+                This->tex_width = make_pow2(text_width);
+            if (text_height > This->tex_height)
+                This->tex_height = make_pow2(text_height);
+
+            if (This->texture)
+            {
+                IDirect3DTexture9_Release(This->texture);
+                DeleteObject(This->bitmap);
+            }
+
+            hr = D3DXCreateTexture(This->device, This->tex_width, 
This->tex_height, 1, 0,
+                                   D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, 
&This->texture);
+            if (FAILED(hr))
+            {
+                This->texture = NULL;
+                return 0;
+            }
+
+            header.biSize = sizeof(header);
+            header.biWidth = This->tex_width;
+            header.biHeight = -This->tex_height;
+            header.biPlanes = 1;
+            header.biBitCount = 32;
+            header.biCompression = BI_RGB;
+            header.biSizeImage = sizeof(DWORD) * This->tex_width * 
This->tex_height;
+            header.biXPelsPerMeter = 0;
+            header.biYPelsPerMeter = 0;
+            header.biClrUsed = 0;
+            header.biClrImportant = 0;
+
+            This->bitmap = CreateDIBSection(This->hdc, (const 
BITMAPINFO*)&header,
+                                            DIB_RGB_COLORS, 
(void**)&This->bits, NULL, 0);
+            if (!This->bitmap)
+            {
+                IDirect3DTexture9_Release(This->texture);
+                This->texture = NULL;
+                return 0;
+            }
+
+            SelectObject(This->hdc, This->bitmap);
+        }
+
+        if (FAILED(IDirect3DTexture9_LockRect(This->texture, 0, &locked_rect, 
&text_rect, D3DLOCK_DISCARD)))
+            return 0;
+
+        /* Clear rect */
+        for (i = 0; i < text_height; i++)
+            memset(This->bits + i * This->tex_width * sizeof(DWORD), 0,
+                   text_width * sizeof(DWORD));
+
+        DrawTextW(This->hdc, string, count, &text_rect, format);
+
+        /* All RGB components are equal so take one as alpha and set RGB
+         * color to white, so it can be modulated with color parameter */
+        for (i = 0; i < text_height; i++)
+        {
+            DWORD *src = (DWORD *)This->bits + i * This->tex_width;
+            DWORD *dst = (DWORD *)((BYTE *)locked_rect.pBits + i * 
locked_rect.Pitch);
+            for (j = 0; j < text_width; j++)
+            {
+                *dst++ = (*src++ << 24) | 0xFFFFFF;
+            }
+        }
+
+        IDirect3DTexture9_UnlockRect(This->texture, 0);
+
+        if (!sprite)
+        {
+            hr = D3DXCreateSprite(This->device, &target);
+            if (FAILED(hr))
+                 return 0;
+            ID3DXSprite_Begin(target, 0);
+        }
+
+        hr = target->lpVtbl->Draw(target, This->texture, &text_rect, NULL, 
&position, color);
+
+        if (!sprite)
+        {
+            ID3DXSprite_End(target);
+            ID3DXSprite_Release(target);
+        }
+
+        if (FAILED(hr))
+            return 0;
+    }
+
+    return height;
 }
 
 static HRESULT WINAPI ID3DXFontImpl_OnLostDevice(ID3DXFont *iface)
@@ -296,46 +501,55 @@ HRESULT WINAPI D3DXCreateFontIndirectW(IDirect3DDevice9 
*device, const D3DXFONT_
 
     TRACE("(%p, %p, %p)\n", device, desc, font);
 
-    if( !device || !desc || !font ) return D3DERR_INVALIDCALL;
+    if (!device || !desc || !font) return D3DERR_INVALIDCALL;
 
-    /* the device MUST support D3DFMT_A8R8G8B8 */
+    TRACE("desc: %d %d %d %d %d %d %d %d %d %s\n", desc->Height, desc->Width, 
desc->Weight, desc->MipLevels, desc->Italic,
+            desc->CharSet, desc->OutputPrecision, desc->Quality, 
desc->PitchAndFamily, debugstr_w(desc->FaceName));
+
+    /* The device MUST support D3DFMT_A8R8G8B8 */
     IDirect3DDevice9_GetDirect3D(device, &d3d);
     IDirect3DDevice9_GetCreationParameters(device, &cpars);
     IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
     hr = IDirect3D9_CheckDeviceFormat(d3d, cpars.AdapterOrdinal, 
cpars.DeviceType, mode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
-    if(FAILED(hr)) {
+    if (FAILED(hr))
+    {
         IDirect3D9_Release(d3d);
         return D3DXERR_INVALIDDATA;
     }
     IDirect3D9_Release(d3d);
 
-    object = HeapAlloc(GetProcessHeap(), 0, sizeof(struct d3dx_font));
-    if(object==NULL) {
-        *font=NULL;
+    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct 
d3dx_font));
+    if (!object)
+    {
+        *font = NULL;
         return E_OUTOFMEMORY;
     }
     object->ID3DXFont_iface.lpVtbl = &D3DXFont_Vtbl;
-    object->ref=1;
-    object->device=device;
-    object->desc=*desc;
+    object->ref = 1;
+    object->device = device;
+    object->desc = *desc;
 
     object->hdc = CreateCompatibleDC(NULL);
-    if( !object->hdc ) {
+    if (!object->hdc)
+    {
         HeapFree(GetProcessHeap(), 0, object);
         return D3DXERR_INVALIDDATA;
     }
 
     object->hfont = CreateFontW(desc->Height, desc->Width, 0, 0, desc->Weight, 
desc->Italic, FALSE, FALSE, desc->CharSet,
                                 desc->OutputPrecision, CLIP_DEFAULT_PRECIS, 
desc->Quality, desc->PitchAndFamily, desc->FaceName);
-    if( !object->hfont ) {
+    if (!object->hfont)
+    {
         DeleteDC(object->hdc);
         HeapFree(GetProcessHeap(), 0, object);
         return D3DXERR_INVALIDDATA;
     }
     SelectObject(object->hdc, object->hfont);
+    SetTextColor(object->hdc, 0x00ffffff);
+    SetBkColor(object->hdc, 0x00000000);
 
     IDirect3DDevice9_AddRef(device);
-    *font=&object->ID3DXFont_iface;
+    *font = &object->ID3DXFont_iface;
 
     return D3D_OK;
 }
diff --git a/dll/directx/wine/d3dx9_36/line.c b/dll/directx/wine/d3dx9_36/line.c
index e1b691a07b..356d54fbd0 100644
--- a/dll/directx/wine/d3dx9_36/line.c
+++ b/dll/directx/wine/d3dx9_36/line.c
@@ -17,7 +17,12 @@
  *
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 struct d3dx9_line
 {
diff --git a/dll/directx/wine/d3dx9_36/d3dx9_36_main.c 
b/dll/directx/wine/d3dx9_36/main.c
similarity index 71%
rename from dll/directx/wine/d3dx9_36/d3dx9_36_main.c
rename to dll/directx/wine/d3dx9_36/main.c
index 01c5219bf0..a256d42526 100644
--- a/dll/directx/wine/d3dx9_36/d3dx9_36_main.c
+++ b/dll/directx/wine/d3dx9_36/main.c
@@ -20,11 +20,14 @@
  *
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "initguid.h"
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
-/***********************************************************************
- * DllMain.
- */
 BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
 {
     switch(reason)
@@ -38,14 +41,13 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void 
*reserved)
     return TRUE;
 }
 
-/***********************************************************************
- * D3DXCheckVersion
- * Checks whether we are compiling against the correct d3d and d3dx library.
- */
-BOOL WINAPI D3DXCheckVersion(UINT d3dsdkvers, UINT d3dxsdkvers)
+BOOL WINAPI D3DXCheckVersion(UINT d3d_sdk_ver, UINT d3dx_sdk_ver)
+{
+    return d3d_sdk_ver == D3D_SDK_VERSION && d3dx_sdk_ver == D3DX_SDK_VERSION;
+}
+
+DWORD WINAPI D3DXCpuOptimizations(BOOL enable)
 {
-    if(d3dsdkvers==D3D_SDK_VERSION && d3dxsdkvers==36)
-        return TRUE;
-    else
-        return FALSE;
+    FIXME("%#x - stub\n", enable);
+    return 0;
 }
diff --git a/dll/directx/wine/d3dx9_36/math.c b/dll/directx/wine/d3dx9_36/math.c
index 2f5a473081..856e987cb9 100644
--- a/dll/directx/wine/d3dx9_36/math.c
+++ b/dll/directx/wine/d3dx9_36/math.c
@@ -22,7 +22,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 struct ID3DXMatrixStackImpl
 {
@@ -2568,27 +2573,27 @@ FLOAT * WINAPI D3DXSHMultiply3(FLOAT *out, const FLOAT 
*a, const FLOAT *b)
 
     out[0] = 0.28209479f * a[0] * b[0];
 
-    ta = 0.28209479f * a[0] - 0.12615662f * a[6] - 0.21850968f * a[8];
-    tb = 0.28209479f * b[0] - 0.12615662f * b[6] - 0.21850968f * b[8];
+    ta = 0.28209479f * a[0] - 0.12615663f * a[6] - 0.21850969f * a[8];
+    tb = 0.28209479f * b[0] - 0.12615663f * b[6] - 0.21850969f * b[8];
     out[1] = ta * b[1] + tb * a[1];
     t = a[1] * b[1];
     out[0] += 0.28209479f * t;
-    out[6] = -0.12615662f * t;
-    out[8] = -0.21850968f * t;
+    out[6] = -0.12615663f * t;
+    out[8] = -0.21850969f * t;
 
-    ta = 0.21850968f * a[5];
-    tb = 0.21850968f * b[5];
+    ta = 0.21850969f * a[5];
+    tb = 0.21850969f * b[5];
     out[1] += ta * b[2] + tb * a[2];
     out[2] = ta * b[1] + tb * a[1];
     t = a[1] * b[2] +a[2] * b[1];
-    out[5] = 0.21850968f * t;
+    out[5] = 0.21850969f * t;
 
-    ta = 0.21850968f * a[4];
-    tb = 0.21850968f * b[4];
+    ta = 0.21850969f * a[4];
+    tb = 0.21850969f * b[4];
     out[1] += ta * b[3] + tb * a[3];
     out[3]  = ta * b[1] + tb * a[1];
     t = a[1] * b[3] + a[3] * b[1];
-    out[4] = 0.21850968f * t;
+    out[4] = 0.21850969f * t;
 
     ta = 0.28209480f * a[0] + 0.25231326f * a[6];
     tb = 0.28209480f * b[0] + 0.25231326f * b[6];
@@ -2624,14 +2629,14 @@ FLOAT * WINAPI D3DXSHMultiply3(FLOAT *out, const FLOAT 
*a, const FLOAT *b)
     out[4] += ta * b[5] + tb * a[5];
     out[5] += ta * b[4] + tb * a[4];
     t = a[4] * b[5] + a[5] * b[4];
-    out[7] += 0.15607834f * t;
+    out[7] += 0.15607835f * t;
 
-    ta = 0.28209479f * a[0] + 0.09011186f * a[6] - 0.15607835f * a[8];
-    tb = 0.28209479f * b[0] + 0.09011186f * b[6] - 0.15607835f * b[8];
+    ta = 0.28209479f * a[0] + 0.09011188f * a[6] - 0.15607835f * a[8];
+    tb = 0.28209479f * b[0] + 0.09011188f * b[6] - 0.15607835f * b[8];
     out[5] += ta * b[5] + tb * a[5];
     t = a[5] * b[5];
     out[0] += 0.28209479f * t;
-    out[6] += 0.09011186f * t;
+    out[6] += 0.09011188f * t;
     out[8] -= 0.15607835f * t;
 
     ta = 0.28209480f * a[0];
@@ -2641,12 +2646,12 @@ FLOAT * WINAPI D3DXSHMultiply3(FLOAT *out, const FLOAT 
*a, const FLOAT *b)
     out[0] += 0.28209480f * t;
     out[6] += 0.18022376f * t;
 
-    ta = 0.28209479f * a[0] + 0.09011186f * a[6] + 0.15607835f * a[8];
-    tb = 0.28209479f * b[0] + 0.09011186f * b[6] + 0.15607835f * b[8];
+    ta = 0.28209479f * a[0] + 0.09011188f * a[6] + 0.15607835f * a[8];
+    tb = 0.28209479f * b[0] + 0.09011188f * b[6] + 0.15607835f * b[8];
     out[7] += ta * b[7] + tb * a[7];
     t = a[7] * b[7];
     out[0] += 0.28209479f * t;
-    out[6] += 0.09011186f * t;
+    out[6] += 0.09011188f * t;
     out[8] += 0.15607835f * t;
 
     ta = 0.28209479f * a[0] - 0.18022375f * a[6];
diff --git a/dll/directx/wine/d3dx9_36/mesh.c b/dll/directx/wine/d3dx9_36/mesh.c
index 57b2aeb1a1..3dd881ee1c 100644
--- a/dll/directx/wine/d3dx9_36/mesh.c
+++ b/dll/directx/wine/d3dx9_36/mesh.c
@@ -24,17 +24,24 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
 
+#include <assert.h>
 #ifdef HAVE_FLOAT_H
 # include <float.h>
 #endif
 
+#include "d3dx9_private.h"
+#undef MAKE_DDHRESULT
+#include "dxfile.h"
 #include "rmxfguid.h"
 #include "rmxftmpl.h"
-
+#include "wine/unicode.h"
 #include "wine/list.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+
 struct d3dx9_mesh
 {
     ID3DXMesh ID3DXMesh_iface;
@@ -1688,11 +1695,7 @@ static HRESULT WINAPI 
d3dx9_mesh_OptimizeInplace(ID3DXMesh *iface, DWORD flags,
         if (FAILED(hr)) goto cleanup;
     } else if (flags & D3DXMESHOPT_ATTRSORT) {
         if (!(flags & D3DXMESHOPT_IGNOREVERTS))
-        {
             FIXME("D3DXMESHOPT_ATTRSORT vertex reordering not implemented.\n");
-            hr = E_NOTIMPL;
-            goto cleanup;
-        }
 
         hr = iface->lpVtbl->LockAttributeBuffer(iface, 0, &attrib_buffer);
         if (FAILED(hr)) goto cleanup;
@@ -2333,7 +2336,7 @@ UINT WINAPI D3DXGetDeclVertexSize(const D3DVERTEXELEMENT9 
*decl, DWORD stream_id
 
         if (element->Stream != stream_idx) continue;
 
-        if (element->Type >= sizeof(d3dx_decltype_size) / 
sizeof(*d3dx_decltype_size))
+        if (element->Type >= ARRAY_SIZE(d3dx_decltype_size))
         {
             FIXME("Unhandled element type %#x, size will be incorrect.\n", 
element->Type);
             continue;
@@ -3325,6 +3328,13 @@ static HRESULT parse_mesh(ID3DXFileData *filedata, 
struct mesh_data *mesh_data,
         goto end;
     }
 
+    if ((provide_flags & PROVIDE_SKININFO) && !mesh_data->skin_info)
+    {
+        hr = create_dummy_skin(&mesh_data->skin_info);
+        if (FAILED(hr))
+            goto end;
+    }
+
     hr = D3D_OK;
 
 end:
@@ -5159,7 +5169,7 @@ HRESULT WINAPI D3DXCreateTeapot(struct IDirect3DDevice9 
*device,
 {
     FIXME("(%p, %p, %p): stub\n", device, mesh, adjacency);
 
-    return E_NOTIMPL;
+    return D3DXCreateSphere(device, 1.0f, 4, 4, mesh, adjacency);
 }
 
 HRESULT WINAPI D3DXCreateTextA(struct IDirect3DDevice9 *device, HDC hdc, const 
char *text, float deviation,
@@ -7177,6 +7187,33 @@ cleanup:
     return hr;
 }
 
+
+/*************************************************************************
+ * D3DXOptimizeVertices    (D3DX9_36.@)
+ */
+HRESULT WINAPI D3DXOptimizeVertices(const void *indices, UINT num_faces,
+        UINT num_vertices, BOOL indices_are_32bit, DWORD *vertex_remap)
+{
+    UINT i;
+
+    FIXME("indices %p, num_faces %u, num_vertices %u, indices_are_32bit %#x, 
vertex_remap %p semi-stub.\n",
+            indices, num_faces, num_vertices, indices_are_32bit, vertex_remap);
+
+    if (!vertex_remap)
+    {
+        WARN("vertex remap pointer is NULL.\n");
+        return D3DERR_INVALIDCALL;
+    }
+
+    for (i = 0; i < num_vertices; i++)
+    {
+        vertex_remap[i] = i;
+    }
+
+    return D3D_OK;
+}
+
+
 /*************************************************************************
  * D3DXOptimizeFaces    (D3DX9_36.@)
  *
@@ -7500,6 +7537,24 @@ done:
     return hr;
 }
 
+/*************************************************************************
+ * D3DXComputeTangent    (D3DX9_36.@)
+ */
+HRESULT WINAPI D3DXComputeTangent(ID3DXMesh *mesh, DWORD stage_idx, DWORD 
tangent_idx,
+        DWORD binorm_idx, DWORD wrap, const DWORD *adjacency)
+{
+    TRACE("mesh %p, stage_idx %d, tangent_idx %d, binorm_idx %d, wrap %d, 
adjacency %p.\n",
+           mesh, stage_idx, tangent_idx, binorm_idx, wrap, adjacency);
+
+    return D3DXComputeTangentFrameEx( mesh, D3DDECLUSAGE_TEXCOORD, stage_idx,
+            ( binorm_idx == D3DX_DEFAULT ) ? D3DX_DEFAULT : 
D3DDECLUSAGE_BINORMAL,
+            binorm_idx,
+            ( tangent_idx == D3DX_DEFAULT ) ? D3DX_DEFAULT : 
D3DDECLUSAGE_TANGENT,
+            tangent_idx, D3DX_DEFAULT, 0,
+            ( wrap ? D3DXTANGENT_WRAP_UV : 0 ) | D3DXTANGENT_GENERATE_IN_PLACE 
| D3DXTANGENT_ORTHOGONALIZE_FROM_U,
+            adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
+}
+
 /*************************************************************************
  * D3DXComputeNormals    (D3DX9_36.@)
  */
@@ -7519,6 +7574,18 @@ HRESULT WINAPI D3DXComputeNormals(struct ID3DXBaseMesh 
*mesh, const DWORD *adjac
             adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL);
 }
 
+/*************************************************************************
+ * D3DXComputeNormalMap    (D3DX9_36.@)
+ */
+HRESULT WINAPI D3DXComputeNormalMap(IDirect3DTexture9 *texture, 
IDirect3DTexture9 *src_texture,
+        const PALETTEENTRY *src_palette, DWORD flags, DWORD channel, FLOAT 
amplitude)
+{
+    FIXME("texture %p, src_texture %p, src_palette %p, flags %#x, channel %u, 
amplitude %f stub.\n",
+            texture, src_texture, src_palette, flags, channel, amplitude);
+
+    return D3D_OK;
+}
+
 /*************************************************************************
  * D3DXIntersect    (D3DX9_36.@)
  */
diff --git a/dll/directx/wine/d3dx9_36/precomp.h 
b/dll/directx/wine/d3dx9_36/precomp.h
new file mode 100644
index 0000000000..30ad1cf918
--- /dev/null
+++ b/dll/directx/wine/d3dx9_36/precomp.h
@@ -0,0 +1,28 @@
+
+#ifndef __WINE_D3DX9_36_PRECOMP_H
+#define __WINE_D3DX9_36_PRECOMP_H
+
+#include <config.h>
+#include <wine/port.h>
+
+#include <assert.h>
+#include <stdarg.h>
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#define COBJMACROS
+
+#include <windef.h>
+#include <winbase.h>
+#include <wingdi.h>
+#include <winuser.h>
+
+#include <wine/unicode.h>
+
+#include "d3dx9_private.h"
+
+#endif /* __WINE_D3DX9_36_PRECOMP_H */
diff --git a/dll/directx/wine/d3dx9_36/preshader.c 
b/dll/directx/wine/d3dx9_36/preshader.c
index 416f05b15a..ef27149d82 100644
--- a/dll/directx/wine/d3dx9_36/preshader.c
+++ b/dll/directx/wine/d3dx9_36/preshader.c
@@ -16,7 +16,15 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+#include <float.h>
+#include <assert.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 /* ReactOS FIXME: Insect */
 #define fmin min
diff --git a/dll/directx/wine/d3dx9_36/render.c 
b/dll/directx/wine/d3dx9_36/render.c
index 02e6caa8eb..ad8330784d 100644
--- a/dll/directx/wine/d3dx9_36/render.c
+++ b/dll/directx/wine/d3dx9_36/render.c
@@ -17,7 +17,12 @@
  *
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 struct device_state
 {
diff --git a/dll/directx/wine/d3dx9_36/shader.c 
b/dll/directx/wine/d3dx9_36/shader.c
index 48e49a2982..2bbc6b79e0 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
@@ -18,12 +19,16 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
-
+#include "config.h"
+#include "wine/port.h"
 #include <stdio.h>
 
+#include "d3dx9_private.h"
+#include "d3dcommon.h"
 #include "d3dcompiler.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
+
 /* This function is not declared in the SDK headers yet. */
 HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char 
*filename,
         const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT flags,
@@ -440,6 +445,41 @@ HRESULT WINAPI D3DXCompileShader(const char *data, UINT 
length, const D3DXMACRO
         }
     }
 
+    /* Filter out D3DCompile warning messages that are not present with 
D3DCompileShader */
+    if (SUCCEEDED(hr) && error_msgs && *error_msgs)
+    {
+        char *messages = ID3DXBuffer_GetBufferPointer(*error_msgs);
+        DWORD size     = ID3DXBuffer_GetBufferSize(*error_msgs);
+
+        /* Ensure messages are null terminated for safe processing */
+        if (size) messages[size - 1] = 0;
+
+        while (size > 1)
+        {
+            char *prev, *next;
+
+            /* Warning has the form "warning X3206: ... implicit truncation of 
vector type"
+               but we only search for "X3206:" in case d3dcompiler_43 has 
localization */
+            prev = next = strstr(messages, "X3206:");
+            if (!prev) break;
+
+            /* get pointer to beginning and end of current line */
+            while (prev > messages && *(prev - 1) != '\n') prev--;
+            while (next < messages + size - 1 && *next != '\n') next++;
+            if (next < messages + size - 1 && *next == '\n') next++;
+
+            memmove(prev, next, messages + size - next);
+            size -= (next - prev);
+        }
+
+        /* Only return a buffer if the resulting string is not empty as some 
apps depend on that */
+        if (size <= 1)
+        {
+            ID3DXBuffer_Release(*error_msgs);
+            *error_msgs = NULL;
+        }
+    }
+
     return hr;
 }
 
@@ -2141,10 +2181,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/dll/directx/wine/d3dx9_36/skin.c b/dll/directx/wine/d3dx9_36/skin.c
index 309241ccc0..0a305a9923 100644
--- a/dll/directx/wine/d3dx9_36/skin.c
+++ b/dll/directx/wine/d3dx9_36/skin.c
@@ -2,6 +2,7 @@
  * Skin Info operations specific to D3DX9.
  *
  * Copyright (C) 2011 Dylan Smith
+ * Copyright (C) 2013 Christian Costa
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,7 +19,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 struct bone
 {
@@ -89,7 +95,7 @@ static ULONG WINAPI d3dx9_skin_info_Release(ID3DXSkinInfo 
*iface)
             HeapFree(GetProcessHeap(), 0, skin->bones[i].vertices);
             HeapFree(GetProcessHeap(), 0, skin->bones[i].weights);
         }
-        HeapFree(GetProcessHeap(), 0, skin->bones);
+        if (skin->bones) HeapFree(GetProcessHeap(), 0, skin->bones);
         HeapFree(GetProcessHeap(), 0, skin);
     }
 
@@ -372,10 +378,89 @@ static HRESULT WINAPI 
d3dx9_skin_info_GetDeclaration(ID3DXSkinInfo *iface,
 static HRESULT WINAPI d3dx9_skin_info_UpdateSkinnedMesh(ID3DXSkinInfo *iface, 
const D3DXMATRIX *bone_transforms,
         const D3DXMATRIX *bone_inv_transpose_transforms, const void 
*src_vertices, void *dst_vertices)
 {
-    FIXME("iface %p, bone_transforms %p, bone_inv_transpose_transforms %p, 
src_vertices %p, dst_vertices %p stub!\n",
-            iface, bone_transforms, bone_inv_transpose_transforms, 
src_vertices, dst_vertices);
+    struct d3dx9_skin_info *skin = impl_from_ID3DXSkinInfo(iface);
+    DWORD size = D3DXGetFVFVertexSize(skin->fvf);
+    DWORD i, j;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, bone_transforms %p, bone_inv_transpose_transforms %p, 
src_vertices %p, dst_vertices %p\n",
+            skin, bone_transforms, bone_inv_transpose_transforms, 
src_vertices, dst_vertices);
+
+    if (bone_inv_transpose_transforms)
+        FIXME("Skinning vertices with two position elements not supported\n");
+
+    if ((skin->fvf & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
+        FIXME("Vertex type %#x not supported\n", skin->fvf & 
D3DFVF_POSITION_MASK);
+        return E_FAIL;
+    }
+
+    /* Reset all positions */
+    for (i = 0; i < skin->num_vertices; i++) {
+        D3DXVECTOR3 *position = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * i);
+        position->x = 0.0f;
+        position->y = 0.0f;
+        position->z = 0.0f;
+    }
+
+    /* Update positions that are influenced by bones */
+    for (i = 0; i < skin->num_bones; i++) {
+        D3DXMATRIX bone_inverse, matrix;
+
+        D3DXMatrixInverse(&bone_inverse, NULL, &skin->bones[i].transform);
+        D3DXMatrixMultiply(&matrix, &bone_transforms[i], &bone_inverse);
+        D3DXMatrixMultiply(&matrix, &matrix, &skin->bones[i].transform);
+
+        for (j = 0; j < skin->bones[i].num_influences; j++) {
+            D3DXVECTOR3 position;
+            D3DXVECTOR3 *position_src = (D3DXVECTOR3*)((BYTE*)src_vertices + 
size * skin->bones[i].vertices[j]);
+            D3DXVECTOR3 *position_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices + 
size * skin->bones[i].vertices[j]);
+            FLOAT weight = skin->bones[i].weights[j];
+
+            D3DXVec3TransformCoord(&position, position_src, &matrix);
+            position_dest->x += weight * position.x;
+            position_dest->y += weight * position.y;
+            position_dest->z += weight * position.z;
+        }
+    }
+
+    if (skin->fvf & D3DFVF_NORMAL) {
+        /* Reset all normals */
+        for (i = 0; i < skin->num_vertices; i++) {
+            D3DXVECTOR3 *normal = (D3DXVECTOR3*)((BYTE*)dst_vertices + size * 
i + sizeof(D3DXVECTOR3));
+            normal->x = 0.0f;
+            normal->y = 0.0f;
+            normal->z = 0.0f;
+        }
+
+        /* Update normals that are influenced by bones */
+        for (i = 0; i < skin->num_bones; i++) {
+            D3DXMATRIX bone_inverse, matrix;
+
+            D3DXMatrixInverse(&bone_inverse, NULL, &skin->bones[i].transform);
+            D3DXMatrixMultiply(&matrix, &skin->bones[i].transform, 
&bone_transforms[i]);
+
+            for (j = 0; j < skin->bones[i].num_influences; j++) {
+                D3DXVECTOR3 normal;
+                D3DXVECTOR3 *normal_src = (D3DXVECTOR3*)((BYTE*)src_vertices + 
size * skin->bones[i].vertices[j] + sizeof(D3DXVECTOR3));
+                D3DXVECTOR3 *normal_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices 
+ size * skin->bones[i].vertices[j] + sizeof(D3DXVECTOR3));
+                FLOAT weight = skin->bones[i].weights[j];
+
+                D3DXVec3TransformNormal(&normal, normal_src, &bone_inverse);
+                D3DXVec3TransformNormal(&normal, &normal, &matrix);
+                normal_dest->x += weight * normal.x;
+                normal_dest->y += weight * normal.y;
+                normal_dest->z += weight * normal.z;
+            }
+        }
+
+        /* Normalize all normals that are influenced by bones*/
+        for (i = 0; i < skin->num_vertices; i++) {
+            D3DXVECTOR3 *normal_dest = (D3DXVECTOR3*)((BYTE*)dst_vertices + (i 
* size) + sizeof(D3DXVECTOR3));
+            if ((normal_dest->x != 0.0f) && (normal_dest->y != 0.0f) && 
(normal_dest->z != 0.0f))
+                D3DXVec3Normalize(normal_dest, normal_dest);
+        }
+    }
+
+    return D3D_OK;
 }
 
 static HRESULT WINAPI d3dx9_skin_info_ConvertToBlendedMesh(ID3DXSkinInfo 
*iface, ID3DXMesh *mesh_in,
@@ -490,3 +575,23 @@ HRESULT WINAPI D3DXCreateSkinInfoFVF(DWORD num_vertices, 
DWORD fvf, DWORD num_bo
 
     return D3DXCreateSkinInfo(num_vertices, declaration, num_bones, skin_info);
 }
+
+HRESULT create_dummy_skin(ID3DXSkinInfo **iface)
+{
+    static const D3DVERTEXELEMENT9 empty_declaration = D3DDECL_END();
+    struct d3dx9_skin_info *object = NULL;
+
+    object = HeapAlloc(GetProcessHeap(), 0, sizeof(*object));
+    if (!object) return E_OUTOFMEMORY;
+
+    object->ID3DXSkinInfo_iface.lpVtbl = &d3dx9_skin_info_vtbl;
+    object->ref = 1;
+    object->num_vertices = 0;
+    object->num_bones = 0;
+    object->vertex_declaration[0] = empty_declaration;
+    object->fvf = 0;
+    object->bones = NULL;
+
+    *iface = &object->ID3DXSkinInfo_iface;
+    return D3D_OK;
+}
diff --git a/dll/directx/wine/d3dx9_36/sprite.c 
b/dll/directx/wine/d3dx9_36/sprite.c
index ba7181b42e..2ff2b415c8 100644
--- a/dll/directx/wine/d3dx9_36/sprite.c
+++ b/dll/directx/wine/d3dx9_36/sprite.c
@@ -17,7 +17,12 @@
  *
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 /* the combination of all possible D3DXSPRITE flags */
 #define D3DXSPRITE_FLAGLIMIT 511
diff --git a/dll/directx/wine/d3dx9_36/surface.c 
b/dll/directx/wine/d3dx9_36/surface.c
index 321265fbaa..a1e56bda6d 100644
--- a/dll/directx/wine/d3dx9_36/surface.c
+++ b/dll/directx/wine/d3dx9_36/surface.c
@@ -18,13 +18,19 @@
  *
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
 
-#include <ole2.h>
-#include <wine/wined3d.h>
+#include "d3dx9_private.h"
+
+#include "initguid.h"
+#include "ole2.h"
+#include "wincodec.h"
+
+#include "wine/wined3d.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
-#include <initguid.h>
-#include <wincodec.h>
 
 /* Wine-specific WIC GUIDs */
 DEFINE_GUID(GUID_WineContainerFormatTga, 
0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47,0x3f,0xc1,0x7c,0xd3,0x22);
@@ -49,7 +55,7 @@ static D3DFORMAT wic_guid_to_d3dformat(const GUID *guid)
 {
     unsigned int i;
 
-    for (i = 0; i < sizeof(wic_pixel_formats) / sizeof(wic_pixel_formats[0]); 
i++)
+    for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); i++)
     {
         if (IsEqualGUID(wic_pixel_formats[i].wic_guid, guid))
             return wic_pixel_formats[i].d3dformat;
@@ -62,7 +68,7 @@ static const GUID *d3dformat_to_wic_guid(D3DFORMAT format)
 {
     unsigned int i;
 
-    for (i = 0; i < sizeof(wic_pixel_formats) / sizeof(wic_pixel_formats[0]); 
i++)
+    for (i = 0; i < ARRAY_SIZE(wic_pixel_formats); i++)
     {
         if (wic_pixel_formats[i].d3dformat == format)
             return wic_pixel_formats[i].wic_guid;
@@ -106,6 +112,7 @@ static const GUID *d3dformat_to_wic_guid(D3DFORMAT format)
 #define DDS_PF_RGB 0x40
 #define DDS_PF_YUV 0x200
 #define DDS_PF_LUMINANCE 0x20000
+#define DDS_PF_BUMPLUMINANCE 0x40000
 #define DDS_PF_BUMPDUDV 0x80000
 
 struct dds_pixel_format
@@ -160,7 +167,7 @@ static D3DFORMAT dds_fourcc_to_d3dformat(DWORD fourcc)
         D3DFMT_A32B32G32R32F,
     };
 
-    for (i = 0; i < sizeof(known_fourcc) / sizeof(known_fourcc[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(known_fourcc); i++)
     {
         if (known_fourcc[i] == fourcc)
             return fourcc;
@@ -199,7 +206,7 @@ static D3DFORMAT dds_rgb_to_d3dformat(const struct 
dds_pixel_format *pixel_forma
 {
     unsigned int i;
 
-    for (i = 0; i < sizeof(rgb_pixel_formats) / sizeof(rgb_pixel_formats[0]); 
i++)
+    for (i = 0; i < ARRAY_SIZE(rgb_pixel_formats); i++)
     {
         if (rgb_pixel_formats[i].bpp == pixel_format->bpp
             && rgb_pixel_formats[i].rmask == pixel_format->rmask
@@ -261,6 +268,17 @@ static D3DFORMAT dds_bump_to_d3dformat(const struct 
dds_pixel_format *pixel_form
     return D3DFMT_UNKNOWN;
 }
 
+static D3DFORMAT dds_bump_luminance_to_d3dformat(const struct dds_pixel_format 
*pixel_format)
+{
+    if (pixel_format->bpp == 32 && pixel_format->rmask == 0x000000ff && 
pixel_format->gmask == 0x0000ff00
+            && pixel_format->bmask == 0x00ff0000)
+        return D3DFMT_X8L8V8U8;
+
+    WARN("Unknown bump pixel format (%u, %#x, %#x, %#x, %#x)\n", 
pixel_format->bpp,
+        pixel_format->rmask, pixel_format->gmask, pixel_format->bmask, 
pixel_format->amask);
+    return D3DFMT_UNKNOWN;
+}
+
 static D3DFORMAT dds_pixel_format_to_d3dformat(const struct dds_pixel_format 
*pixel_format)
 {
     TRACE("pixel_format: size %u, flags %#x, fourcc %#x, bpp %u.\n", 
pixel_format->size,
@@ -278,6 +296,8 @@ static D3DFORMAT dds_pixel_format_to_d3dformat(const struct 
dds_pixel_format *pi
         return dds_alpha_to_d3dformat(pixel_format);
     if (pixel_format->flags & DDS_PF_BUMPDUDV)
         return dds_bump_to_d3dformat(pixel_format);
+    if (pixel_format->flags & DDS_PF_BUMPLUMINANCE)
+        return dds_bump_luminance_to_d3dformat(pixel_format);
 
     WARN("Unknown pixel format (flags %#x, fourcc %#x, bpp %u, r %#x, g %#x, b 
%#x, a %#x)\n",
         pixel_format->flags, pixel_format->fourcc, pixel_format->bpp,
@@ -293,7 +313,7 @@ static HRESULT d3dformat_to_dds_pixel_format(struct 
dds_pixel_format *pixel_form
 
     pixel_format->size = sizeof(*pixel_format);
 
-    for (i = 0; i < sizeof(rgb_pixel_formats) / sizeof(rgb_pixel_formats[0]); 
i++)
+    for (i = 0; i < ARRAY_SIZE(rgb_pixel_formats); i++)
     {
         if (rgb_pixel_formats[i].format == d3dformat)
         {
@@ -308,6 +328,14 @@ static HRESULT d3dformat_to_dds_pixel_format(struct 
dds_pixel_format *pixel_form
         }
     }
 
+    /* Reuse dds_fourcc_to_d3dformat as D3DFORMAT and FOURCC are DWORD with 
same values */
+    if (dds_fourcc_to_d3dformat(d3dformat) != D3DFMT_UNKNOWN)
+    {
+        pixel_format->flags |= DDS_PF_FOURCC;
+        pixel_format->fourcc = d3dformat;
+        return D3D_OK;
+    }
+
     WARN("Unknown pixel format %#x\n", d3dformat);
     return E_NOTIMPL;
 }
@@ -516,6 +544,68 @@ static HRESULT save_dds_surface_to_memory(ID3DXBuffer 
**dst_buffer, IDirect3DSur
     return D3D_OK;
 }
 
+static HRESULT get_surface(D3DRESOURCETYPE type, struct IDirect3DBaseTexture9 
*tex,
+        int face, UINT level, struct IDirect3DSurface9 **surf)
+{
+    switch (type)
+    {
+        case D3DRTYPE_TEXTURE:
+            return IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) tex, 
level, surf);
+        case D3DRTYPE_CUBETEXTURE:
+            return 
IDirect3DCubeTexture9_GetCubeMapSurface((IDirect3DCubeTexture9*) tex, face, 
level, surf);
+        default:
+            ERR("Unexpected texture type\n");
+            return E_NOTIMPL;
+    }
+}
+
+HRESULT save_dds_texture_to_memory(ID3DXBuffer **dst_buffer, 
IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
+{
+    HRESULT hr;
+    D3DRESOURCETYPE type;
+    UINT mip_levels;
+    IDirect3DSurface9 *surface;
+
+    type = IDirect3DBaseTexture9_GetType(src_texture);
+
+    if ((type !=  D3DRTYPE_TEXTURE) && (type != D3DRTYPE_CUBETEXTURE) && (type 
!= D3DRTYPE_VOLUMETEXTURE))
+        return D3DERR_INVALIDCALL;
+
+    if (type == D3DRTYPE_CUBETEXTURE)
+    {
+        FIXME("Cube texture not supported yet\n");
+        return E_NOTIMPL;
+    }
+    else if (type == D3DRTYPE_VOLUMETEXTURE)
+    {
+        FIXME("Volume texture not supported yet\n");
+        return E_NOTIMPL;
+    }
+
+    mip_levels = IDirect3DTexture9_GetLevelCount(src_texture);
+
+    if (mip_levels > 1)
+    {
+        FIXME("Mipmap not supported yet\n");
+        return E_NOTIMPL;
+    }
+
+    if (src_palette)
+    {
+        FIXME("Saving surfaces with palettized pixel formats not implemented 
yet\n");
+        return E_NOTIMPL;
+    }
+
+    hr = get_surface(type, src_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, 
&surface);
+
+    if (SUCCEEDED(hr))
+    {
+        hr = save_dds_surface_to_memory(dst_buffer, surface, NULL);
+        IDirect3DSurface9_Release(surface);
+    }
+
+    return hr;
+}
 HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY 
*dst_palette,
     const D3DBOX *dst_box, const void *src_data, const D3DBOX *src_box, DWORD 
filter, D3DCOLOR color_key,
     const D3DXIMAGE_INFO *src_info)
@@ -883,6 +973,24 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void 
*data, UINT datasize,
                 }
             }
 
+            /* For 32 bpp BMP, windowscodecs.dll never returns a format with 
alpha while
+             * d3dx9_xx.dll returns one if at least 1 pixel has a non zero 
alpha component */
+            if (SUCCEEDED(hr) && (info->Format == D3DFMT_X8R8G8B8) && 
(info->ImageFileFormat == D3DXIFF_BMP)) {
+                DWORD size = sizeof(DWORD) * info->Width * info->Height;
+                BYTE *buffer = HeapAlloc(GetProcessHeap(), 0, size);
+                hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, 
sizeof(DWORD) * info->Width, size, buffer);
+                if (SUCCEEDED(hr)) {
+                    DWORD i;
+                    for (i = 0; i < info->Width * info->Height; i++) {
+                        if (buffer[i*4+3]) {
+                            info->Format = D3DFMT_A8R8G8B8;
+                            break;
+                        }
+                    }
+                }
+                HeapFree(GetProcessHeap(), 0, buffer);
+            }
+
             if (frame)
                  IWICBitmapFrameDecode_Release(frame);
 
@@ -1711,6 +1819,27 @@ void point_filter_argb_pixels(const BYTE *src, UINT 
src_row_pitch, UINT src_slic
     }
 }
 
+typedef BOOL (*dxtn_conversion_func)(const BYTE *src, BYTE *dst, DWORD 
pitch_in, DWORD pitch_out,
+                                     enum wined3d_format_id format, unsigned 
int w, unsigned int h);
+
+static dxtn_conversion_func get_dxtn_conversion_func(D3DFORMAT format, BOOL 
encode)
+{
+    switch (format)
+    {
+        case D3DFMT_DXT1:
+            if (!wined3d_dxtn_supported()) return NULL;
+            return encode ? wined3d_dxt1_encode : wined3d_dxt1_decode;
+        case D3DFMT_DXT3:
+            if (!wined3d_dxtn_supported()) return NULL;
+            return encode ? wined3d_dxt3_encode : wined3d_dxt3_decode;
+        case D3DFMT_DXT5:
+            if (!wined3d_dxtn_supported()) return NULL;
+            return encode ? wined3d_dxt5_encode : wined3d_dxt5_decode;
+        default:
+            return NULL;
+    }
+}
+
 /************************************************************
  * D3DXLoadSurfaceFromMemory
  *
@@ -1752,6 +1881,7 @@ HRESULT WINAPI 
D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
     D3DSURFACE_DESC surfdesc;
     D3DLOCKED_RECT lockrect;
     struct volume src_size, dst_size;
+    HRESULT ret = D3D_OK;
 
     TRACE("(%p, %p, %s, %p, %#x, %u, %p, %s, %#x, 0x%08x)\n",
             dst_surface, dst_palette, wine_dbgstr_rect(dst_rect), src_memory, 
src_format,
@@ -1833,8 +1963,15 @@ HRESULT WINAPI 
D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
     }
     else /* Stretching or format conversion. */
     {
-        if (!is_conversion_from_supported(srcformatdesc)
-                || !is_conversion_to_supported(destformatdesc))
+        dxtn_conversion_func pre_convert, post_convert;
+        void *tmp_src_memory = NULL, *tmp_dst_memory = NULL;
+        UINT tmp_src_pitch, tmp_dst_pitch;
+
+        pre_convert  = get_dxtn_conversion_func(srcformatdesc->format, FALSE);
+        post_convert = get_dxtn_conversion_func(destformatdesc->format, TRUE);
+
+        if ((!pre_convert && !is_conversion_from_supported(srcformatdesc)) ||
+                (!post_convert && !is_conversion_to_supported(destformatdesc)))
         {
             FIXME("Unsupported format conversion %#x -> %#x.\n", src_format, 
surfdesc.Format);
             return E_NOTIMPL;
@@ -1843,10 +1980,52 @@ HRESULT WINAPI 
D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
         if (FAILED(IDirect3DSurface9_LockRect(dst_surface, &lockrect, 
dst_rect, 0)))
             return D3DXERR_INVALIDDATA;
 
+        /* handle pre-conversion */
+        if (pre_convert)
+        {
+            tmp_src_memory = HeapAlloc(GetProcessHeap(), 0, src_size.width * 
src_size.height * sizeof(DWORD));
+            if (!tmp_src_memory)
+            {
+                ret = E_OUTOFMEMORY;
+                goto error;
+            }
+            tmp_src_pitch = src_size.width * sizeof(DWORD);
+            if (!pre_convert(src_memory, tmp_src_memory, src_pitch, 
tmp_src_pitch,
+                    WINED3DFMT_B8G8R8A8_UNORM, src_size.width, 
src_size.height))
+            {
+                ret = E_FAIL;
+                goto error;
+            }
+            srcformatdesc = get_format_info(D3DFMT_A8R8G8B8);
+        }
+        else
+        {
+            tmp_src_memory = (void *)src_memory;
+            tmp_src_pitch  = src_pitch;
+        }
+
+        /* handle post-conversion */
+        if (post_convert)
+        {
+            tmp_dst_memory = HeapAlloc(GetProcessHeap(), 0, dst_size.width * 
dst_size.height * sizeof(DWORD));
+            if (!tmp_dst_memory)
+            {
+                ret = E_OUTOFMEMORY;
+                goto error;
+            }
+            tmp_dst_pitch = dst_size.width * sizeof(DWORD);
+            destformatdesc = get_format_info(D3DFMT_A8R8G8B8);
+        }
+        else
+        {
+            tmp_dst_memory = lockrect.pBits;
+            tmp_dst_pitch  = lockrect.Pitch;
+        }
+
         if ((filter & 0xf) == D3DX_FILTER_NONE)
         {
-            convert_argb_pixels(src_memory, src_pitch, 0, &src_size, 
srcformatdesc,
-                    lockrect.pBits, lockrect.Pitch, 0, &dst_size, 
destformatdesc, color_key, src_palette);
+            convert_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, &src_size, 
srcformatdesc,
+                    tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, 
destformatdesc, color_key, src_palette);
         }
         else /* if ((filter & 0xf) == D3DX_FILTER_POINT) */
         {
@@ -1855,14 +2034,30 @@ HRESULT WINAPI 
D3DXLoadSurfaceFromMemory(IDirect3DSurface9 *dst_surface,
 
             /* Always apply a point filter until D3DX_FILTER_LINEAR,
              * D3DX_FILTER_TRIANGLE and D3DX_FILTER_BOX are implemented. */
-            point_filter_argb_pixels(src_memory, src_pitch, 0, &src_size, 
srcformatdesc,
-                    lockrect.pBits, lockrect.Pitch, 0, &dst_size, 
destformatdesc, color_key, src_palette);
+            point_filter_argb_pixels(tmp_src_memory, tmp_src_pitch, 0, 
&src_size, srcformatdesc,
+                    tmp_dst_memory, tmp_dst_pitch, 0, &dst_size, 
destformatdesc, color_key, src_palette);
         }
 
+        /* handle post-conversion */
+        if (post_convert)
+        {
+            if (!post_convert(tmp_dst_memory, lockrect.pBits, tmp_dst_pitch, 
lockrect.Pitch,
+                    WINED3DFMT_B8G8R8A8_UNORM, dst_size.width, 
dst_size.height))
+            {
+                ret = E_FAIL;
+                goto error;
+            }
+        }
+
+error:
+        if (pre_convert)
+            HeapFree(GetProcessHeap(), 0, tmp_src_memory);
+        if (post_convert)
+            HeapFree(GetProcessHeap(), 0, tmp_dst_memory);
         IDirect3DSurface9_UnlockRect(dst_surface);
     }
 
-    return D3D_OK;
+    return ret;
 }
 
 /************************************************************
diff --git a/dll/directx/wine/d3dx9_36/texture.c 
b/dll/directx/wine/d3dx9_36/texture.c
index f4e3231483..fa5ccfc66e 100644
--- a/dll/directx/wine/d3dx9_36/texture.c
+++ b/dll/directx/wine/d3dx9_36/texture.c
@@ -19,7 +19,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 /* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */
 static BOOL is_pow2(UINT num)
@@ -195,7 +200,7 @@ static D3DFORMAT get_luminance_replacement_format(D3DFORMAT 
format)
     };
     unsigned int i;
 
-    for (i = 0; i < sizeof(luminance_replacements) / 
sizeof(luminance_replacements[0]); ++i)
+    for (i = 0; i < ARRAY_SIZE(luminance_replacements); ++i)
         if (format == luminance_replacements[i].luminance_format)
             return luminance_replacements[i].replacement_format;
     return format;
@@ -330,10 +335,10 @@ HRESULT WINAPI D3DXCheckTextureRequirements(struct 
IDirect3DDevice9 *device, UIN
 
     if (fmt->block_width != 1 || fmt->block_height != 1)
     {
-        if (w < fmt->block_width)
-            w = fmt->block_width;
-        if (h < fmt->block_height)
-            h = fmt->block_height;
+        if (w % fmt->block_width)
+            w += fmt->block_width - w % fmt->block_width;
+        if (h % fmt->block_height)
+            h += fmt->block_height - h % fmt->block_height;
     }
 
     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
@@ -552,7 +557,7 @@ static D3DFORMAT get_alpha_replacement_format(D3DFORMAT 
format)
     };
     unsigned int i;
 
-    for (i = 0; i < sizeof(replacement_formats) / 
sizeof(replacement_formats[0]); ++i)
+    for (i = 0; i < ARRAY_SIZE(replacement_formats); ++i)
         if (replacement_formats[i].orig_format == format)
             return replacement_formats[i].replacement_format;
     return format;
@@ -1887,10 +1892,7 @@ HRESULT WINAPI D3DXSaveTextureToFileInMemory(ID3DXBuffer 
**dst_buffer, D3DXIMAGE
     if (!dst_buffer || !src_texture) return D3DERR_INVALIDCALL;
 
     if (file_format == D3DXIFF_DDS)
-    {
-        FIXME("DDS file format isn't supported yet\n");
-        return E_NOTIMPL;
-    }
+        return save_dds_texture_to_memory(dst_buffer, src_texture, 
src_palette);
 
     type = IDirect3DBaseTexture9_GetType(src_texture);
     switch (type)
diff --git a/dll/directx/wine/d3dx9_36/util.c b/dll/directx/wine/d3dx9_36/util.c
index 47f9637d83..029e50073c 100644
--- a/dll/directx/wine/d3dx9_36/util.c
+++ b/dll/directx/wine/d3dx9_36/util.c
@@ -17,7 +17,12 @@
  *
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 static void la_from_rgba(const struct vec4 *rgba, struct vec4 *la)
 {
@@ -85,6 +90,7 @@ static const struct pixel_format_desc formats[] =
     {D3DFMT_G32R32F,       { 0, 32, 32,  0}, { 0,  0, 32,  0},  8, 1, 1,  8, 
FORMAT_ARGBF,   NULL,         NULL      },
     {D3DFMT_A32B32G32R32F, {32, 32, 32, 32}, {96,  0, 32, 64}, 16, 1, 1, 16, 
FORMAT_ARGBF,   NULL,         NULL      },
     {D3DFMT_P8,            { 8,  8,  8,  8}, { 0,  0,  0,  0},  1, 1, 1,  1, 
FORMAT_INDEX,   NULL,         index_to_rgba},
+    {D3DFMT_X8L8V8U8,      { 0,  8,  8,  8}, { 0,  0,  8, 16},  4, 1, 1,  4, 
FORMAT_ARGB,    NULL,         NULL      },
     /* marks last element */
     {D3DFMT_UNKNOWN,       { 0,  0,  0,  0}, { 0,  0,  0,  0},  0, 1, 1,  0, 
FORMAT_UNKNOWN, NULL,         NULL      },
 };
@@ -215,7 +221,7 @@ const struct pixel_format_desc *get_format_info(D3DFORMAT 
format)
 
 const struct pixel_format_desc *get_format_info_idx(int idx)
 {
-    if(idx >= sizeof(formats) / sizeof(formats[0]))
+    if(idx >= ARRAY_SIZE(formats))
         return NULL;
     if(formats[idx].format == D3DFMT_UNKNOWN)
         return NULL;
diff --git a/dll/directx/wine/d3dx9_36/volume.c 
b/dll/directx/wine/d3dx9_36/volume.c
index c72dfc5708..f07e552dbe 100644
--- a/dll/directx/wine/d3dx9_36/volume.c
+++ b/dll/directx/wine/d3dx9_36/volume.c
@@ -16,7 +16,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
+
+#include "d3dx9_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 HRESULT WINAPI D3DXLoadVolumeFromFileA(IDirect3DVolume9 *dst_volume,
                                        const PALETTEENTRY *dst_palette,
diff --git a/dll/directx/wine/d3dx9_36/xfile.c 
b/dll/directx/wine/d3dx9_36/xfile.c
index 795b7bc3ff..157545482b 100644
--- a/dll/directx/wine/d3dx9_36/xfile.c
+++ b/dll/directx/wine/d3dx9_36/xfile.c
@@ -17,9 +17,15 @@
  *
  */
 
-#include "d3dx9_36_private.h"
+#include "config.h"
+#include "wine/port.h"
 
-#include <dxfile.h>
+#include "d3dx9_private.h"
+#include "d3dx9xof.h"
+#undef MAKE_DDHRESULT
+#include "dxfile.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
 static HRESULT error_dxfile_to_d3dxfile(HRESULT error)
 {
diff --git a/media/doc/README.WINE b/media/doc/README.WINE
index 5e789914d8..1f00297ce1 100644
--- a/media/doc/README.WINE
+++ b/media/doc/README.WINE
@@ -26,7 +26,7 @@ reactos/dll/directx/wine/d3d8           # Synced to 
WineStaging-3.3
 reactos/dll/directx/wine/d3d9           # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3dcompiler_43 # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3drm          # Synced to WineStaging-3.3
-reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to Wine-3.0
+reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-3.3
 reactos/dll/directx/wine/d3dxof         # Synced to WineStaging-2.9
 reactos/dll/directx/wine/ddraw          # Synced to WineStaging-3.3
 reactos/dll/directx/wine/devenum        # Synced to Wine-3.0

Reply via email to