[Bug 34268] Louisiana Adventure crashes without native d3dx9_36 (D3DXCompileShaderFromFile() needs to call user-supplied include callbacks for resolving primary shader files)

wine-bugs at winehq.org wine-bugs at winehq.org
Sun Aug 18 09:22:20 CDT 2013


http://bugs.winehq.org/show_bug.cgi?id=34268

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |download
             Status|UNCONFIRMED                 |NEW
                URL|                            |http://www.atomicgamer.com/
                   |                            |files/101304/louisiana-adve
                   |                            |nture-demo
                 CC|                            |focht at gmx.net
         Depends on|                            |34275, 29448
            Summary|Louisiana Adventure crashes |Louisiana Adventure crashes
                   |without native d3dx9_36     |without native d3dx9_36
                   |                            |(D3DXCompileShaderFromFile(
                   |                            |) needs to call
                   |                            |user-supplied include
                   |                            |callbacks for resolving
                   |                            |primary shader files)
     Ever Confirmed|0                           |1

--- Comment #3 from Anastasius Focht <focht at gmx.net> 2013-08-18 09:22:20 CDT ---
Hello folks,

confirming, after working around bug 34275 (HTMLStyleSheet_GetIDsOfNames is a
stub) and fixing bug 29448 (GameShield, "SetCurrentDirectoryA calling W API
causes detours recursion"), the game crashes right after "settings" dialog.

It starts successfully if native d3dx9_36.dll is used.

Use the following command line to extract it to right place:

--- snip ---
$ pwd
/home/focht/.wine/drive_c/users/focht/Application Data/Louisiana Adventure

$ find DirectX/ -name "*dx9_36_x86*" -exec cabextract -F d3dx9_36.dll -d . {}
\;
--- snip ---

Test using native override:

--- snip ---
$ pwd
/home/focht/.wine/drive_c/users/focht/Application Data/Louisiana Adventure

$ WINEDLLOVERRIDES=d3dx9_36=n wine ./Louisiana.exe
--- snip ---

Wine builtin (crash):

--- snip ---
$ pwd
/home/focht/.wine/drive_c/users/focht/Application Data/Louisiana Adventure
...
WINEDEBUG=+tid,+seh,+relay,+d3dx wine ./Louisiana.exe >>log.txt 2>&1
...
0025:Call KERNEL32.GetFullPathNameA(035d28c8
"shade3D.dll",00000106,0032f940,0032f93c) ret=00d4e668
0025:Ret  KERNEL32.GetFullPathNameA() retval=0000003f ret=00d4e668
0025:Call KERNEL32.LoadLibraryA(0132aeb8 "shade3D.dll") ret=00d66442
0025:Call PE DLL (proc=0x3d1d346,module=0x3d10000
L"shade3D.dll",reason=PROCESS_ATTACH,res=(nil)) 
...
0025:Call KERNEL32.LoadLibraryA(035ead38 "d3dx9_36.dll") ret=00d66442
0025:Ret  KERNEL32.LoadLibraryA() retval=7c870000 ret=00d66442
...
0025:Call d3dx9_36.D3DXCompileShaderFromFileA(01a6f550
"c:\\users\\focht\\application data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx",03d291e8,0032f884,03d1f8d4
"vsMain",03d1f8dc "vs_2_0",00001000,0032f860,0032f868,0032f864) ret=03d13e0c
0025:Call KERNEL32.MultiByteToWideChar(00000000,00000000,01a6f550
"c:\\users\\focht\\application data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx",ffffffff,00000000,00000000)
ret=7c8bbd66
0025:Ret  KERNEL32.MultiByteToWideChar() retval=00000061 ret=7c8bbd66
0025:Call ntdll.RtlAllocateHeap(00110000,00000000,000000c2) ret=7c8bbd95
0025:Ret  ntdll.RtlAllocateHeap() retval=030053f0 ret=7c8bbd95
0025:Call KERNEL32.MultiByteToWideChar(00000000,00000000,01a6f550
"c:\\users\\focht\\application data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx",ffffffff,030053f0,00000061)
ret=7c8bbddb
0025:Ret  KERNEL32.MultiByteToWideChar() retval=00000061 ret=7c8bbddb
0025:Call KERNEL32.WideCharToMultiByte(00000003,00000000,0032e686
L"c:\\users\\focht\\application data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx",00000060,0032d624,00000fff,00000000,00000000)
ret=00d2ba1f
0025:Ret  KERNEL32.WideCharToMultiByte() retval=00000060 ret=00d2ba1f
0025:Call KERNEL32.GetFullPathNameA(01375e68 "c:\\users\\focht\\application
data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx",00000106,0032e4ac,0032e4a8)
ret=00d4e668
0025:Ret  KERNEL32.GetFullPathNameA() retval=00000060 ret=00d4e668
0025:Call KERNEL32.CreateFileW(030053f0 L"c:\\users\\focht\\application
data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx",80000000,00000001,00000000,00000003,00000000,00000000)
ret=00d70bd1
0025:Ret  KERNEL32.CreateFileW() retval=ffffffff ret=00d70bd1
0025:Call KERNEL32.GetLastError() ret=00d70bd9
0025:Ret  KERNEL32.GetLastError() retval=00000003 ret=00d70bd9
0025:Call KERNEL32.GetLastError() ret=00d6f2cd
0025:Ret  KERNEL32.GetLastError() retval=00000003 ret=00d6f2cd
0025:Call KERNEL32.CloseHandle(00000000) ret=00d70fdd
0025:Ret  KERNEL32.CloseHandle() retval=00000000 ret=00d70fdd
0025:Call KERNEL32.GetLastError() ret=00d6f2cd
0025:Ret  KERNEL32.GetLastError() retval=00000006 ret=00d6f2cd
0025:Call ntdll.RtlFreeHeap(00110000,00000000,030053f0) ret=7c8bbe4d
0025:Ret  ntdll.RtlFreeHeap() retval=00000001 ret=7c8bbe4d
0025:Ret  d3dx9_36.D3DXCompileShaderFromFileA() retval=88760b59 ret=03d13e0c
0025:trace:seh:raise_exception code=c0000005 flags=0 addr=0x3d13e1c ip=03d13e1c
tid=0025
0025:trace:seh:raise_exception  info[0]=00000000
0025:trace:seh:raise_exception  info[1]=00000000
0025:trace:seh:raise_exception  eax=00000000 ebx=00000000 ecx=042dda28
edx=00110064 esi=0032f85f edi=ffffffff
0025:trace:seh:raise_exception  ebp=019bd32c esp=0032f84c cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00010286 
--- snip ---

The game shader wrapper tries to load the shader file with path
"c:\\users\\focht\\application data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx" which obviously
doesn't exist.

If we look for the shader file, we find it embedded in another file:

--- snip ---
[~/.wine/drive_c/users/focht/Application Data/Louisiana Adventure] grep -HR
"vertexcolor.fx" *
Binary file Data/Materials.grf matches
--- snip ---

Wine code for loading from file:

http://source.winehq.org/git/wine.git/blob/1099bb5e76de05718e3cbd43a3d0326883f39cfe:/dlls/d3dx9_36/shader.c#l383

--- snip ---
 383 HRESULT WINAPI D3DXCompileShaderFromFileA(const char *filename, const
D3DXMACRO *defines,
 384         ID3DXInclude *include, const char *entrypoint, const char
*profile, DWORD flags,
 385         ID3DXBuffer **shader, ID3DXBuffer **error_messages,
ID3DXConstantTable **constant_table)
 386 {
 387     LPWSTR filename_w = NULL;
 388     DWORD len;
 389     HRESULT ret;
 390 
 391     if (!filename) return D3DXERR_INVALIDDATA;
 392 
 393     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
 394     filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 395     if (!filename_w) return E_OUTOFMEMORY;
 396     MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
 397 
 398     ret = D3DXCompileShaderFromFileW(filename_w, defines, include,
 399                                      entrypoint, profile, flags,
 400                                      shader, error_messages,
constant_table);
 401 
 402     HeapFree(GetProcessHeap(), 0, filename_w);
 403     return ret;
 404 }
 405
 406 HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const
D3DXMACRO *defines,
 407         ID3DXInclude *include, const char *entrypoint, const char
*profile, DWORD flags,
 408         ID3DXBuffer **shader, ID3DXBuffer **error_messages,
ID3DXConstantTable **constant_table)
 409 {
 410     void *buffer;
 411     DWORD len, filename_len;
 412     HRESULT hr;
 413     struct D3DXIncludeImpl includefromfile;
 414     char *filename_a;
 415 
 416     if (FAILED(map_view_of_file(filename, &buffer, &len)))
 417         return D3DXERR_INVALIDDATA;
 418
...
 445 }
--- snip ---

The Wine helper for loading data files lives in "map_view_of_file"

Source:
http://source.winehq.org/git/wine.git/blob/edb01d2662748125b7ef7d9a1dc21419e33cad20:/dlls/d3dx9_36/util.c#l92

--- snip ---
 111 HRESULT map_view_of_file(LPCWSTR filename, LPVOID *buffer, DWORD *length)
 112 {
 113     HANDLE hfile, hmapping = NULL;
 114 
 115     hfile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, 0,
OPEN_EXISTING, 0, 0);
 116     if(hfile == INVALID_HANDLE_VALUE) goto error;
 117 
 118     *length = GetFileSize(hfile, NULL);
 119     if(*length == INVALID_FILE_SIZE) goto error;
 120 
 121     hmapping = CreateFileMappingW(hfile, NULL, PAGE_READONLY, 0, 0, NULL);
 122     if(!hmapping) goto error;
 123 
 124     *buffer = MapViewOfFile(hmapping, FILE_MAP_READ, 0, 0, 0);
 125     if(*buffer == NULL) goto error;
 126 
 127     CloseHandle(hmapping);
 128     CloseHandle(hfile);
 129 
 130     return S_OK;
 131 
 132 error:
 133     CloseHandle(hmapping);
 134     CloseHandle(hfile);
 135     return HRESULT_FROM_WIN32(GetLastError());
 136 }
--- snip ---

Unfortunately this code doesn't handle the case where the primary shader file
lives in relocated path and/or is embedded in data files.

Running native with more diagnostics gives (force some C++ runtime to builtin,
better diag):

--- snip ---
$ WINEDLLOVERRIDES="d3dx9_36=n;msvcr71,msvcp71=b"
WINEDEBUG=+tid,+seh,+loaddll,+relay,+snoop,+msvcrt wine ./Louisiana.exe
>>log2.txt 2>&1
...
0025:Call KERNEL32.GetFullPathNameA(038528e0
"shade3D.dll",00000106,0032f940,0032f93c) ret=00d4e668
0025:Ret  KERNEL32.GetFullPathNameA() retval=0000003f ret=00d4e668
0025:Call KERNEL32.LoadLibraryA(0132aeb8 "shade3D.dll") ret=00d66442
...
0025:Ret  PE DLL (proc=0x423d346,module=0x4230000
L"shade3D.dll",reason=PROCESS_ATTACH,res=(nil)) retval=1
0025:Ret  KERNEL32.LoadLibraryA() retval=04230000 ret=00d66442
...
0025:Call KERNEL32.LoadLibraryA(0386ad58 "d3dx9_36.dll") ret=00d66442
0025:Ret  KERNEL32.LoadLibraryA() retval=03cc0000 ret=00d66442
...
0025:CALL d3dx9_36.D3DXCompileShaderFromFileA(<unknown, check return>)
ret=04233e0c
...
0025:Call KERNEL32.GetFullPathNameA(030d67a8 "c:\\users\\focht\\application
data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx",00000104,0032f370,0032f324)
ret=03ed01dd
0025:Ret  KERNEL32.GetFullPathNameA() retval=00000060 ret=03ed01dd
0025:Call
msvcp71.??0?$basic_string at DU?$char_traits at D@std@@V?$allocator at D@2@@std@@QAE at PBD@Z(0032f2d0,030d67a8
"c:\\users\\focht\\application data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx") ret=04232f8a
0025:Call ntdll.strlen(030d67a8 "c:\\users\\focht\\application data\\louisiana
adventure\\data\\materials\\common\\generic\\vertexcolor.fx") ret=7c869272
0025:Ret  ntdll.strlen() retval=00000060 ret=7c869272
...
0025:Call
msvcp71.?rfind@?$basic_string at DU?$char_traits at D@std@@V?$allocator at D@2@@std@@QBEIPBDI at Z(0032f1e8,0423fbe8
".",ffffffff) ret=0423809b
...
0025:Ret 
msvcp71.?rfind@?$basic_string at DU?$char_traits at D@std@@V?$allocator at D@2@@std@@QBEIPBDI at Z()
retval=0000005d ret=0423809b
0025:Call
msvcp71.?rfind@?$basic_string at DU?$char_traits at D@std@@V?$allocator at D@2@@std@@QBEIPBDI at Z(0032f1e8,0423fbe4
"\\",ffffffff) ret=042380b3
...
0025:Ret 
msvcp71.?rfind@?$basic_string at DU?$char_traits at D@std@@V?$allocator at D@2@@std@@QBEIPBDI at Z()
retval=00000051 ret=042380b3
0025:Call
msvcp71.?rfind@?$basic_string at DU?$char_traits at D@std@@V?$allocator at D@2@@std@@QBEIPBDI at Z(0032f1e8,0423fbe0
"/",ffffffff) ret=042380cb
...
0025:Call msvcrt.fopen(030b7898 "c:\\users\\focht\\application data\\louisiana
adventure\\data\\materials.grf",0423fc24 "rb") ret=042394ff 
...
<seek>
...
0025:trace:msvcrt:read_i (512), "float4x4\tvCamera\t\t\t:
register(c0);\r\n\r\nstruct VS_OUTPUT\r\n{\r\n\thalf4 pos\t:
POSITION0;\r\n\thalf4 vtxColor\t: COLOR0;\r\n};\r\n\r\nVS_OUTPUT vsMain( half3
pos : POSITION, half4 col : COLOR0)\r\n{\r\n\tVS_OUTPUT ov;\t\r\n\thalf4
position = half4(pos,1);\r\n\tov.pos = mul(position, vCamera);\r"... 
...
0025:RET 
d3dx9_36.D3DXCompileShaderFromFileA(030d67a8,042491e8,0032f884,0423f8d4,0423f8dc,00001000,0032f860,0032f868,0032f864)
retval=00000000 ret=04233e0c 
--- snip ---

The call to D3DXCompileShaderFromFileA() is made from "shade3D.dll"
(04230000...042xxxxx range).
Native "d3dx9_36.dll" is mapped at 03cc0000...040xxxxx range.

The interesting part is from where the msvcrt and C++ runtime function are
called (path separators "\\", "/", dot).
The caller addresses are located again in "shade3D.dll" - so there are indeed
callbacks involved.
The shader file is found embedded in "materials.grf", see msvcrt.fopen
"c:\\users\\focht\\application data\\louisiana adventure\\data\\materials.grf".
The callback seeks in data file and loads the content of the requested shader.

So it seems that various games _expect_ that "include" user callbacks are
called from D3DXCompileShaderFromFile() to be able to resolve and load the
primary shader file with their own shader loader code (if LPD3DXINCLUDE
interface pointer is present and valid).
This also applies to other API that load from file, see MSDN for
ID3DXInclude::Open method for potentially affected API.
The MSDN documentation states this is for handling #include directives but this
seems not the whole truth.

Implementing this should fix various games where the shader loading procedure
fails due to seemingly non-existing/invalid paths.

$ wine --version
wine-1.7.0-137-g029c112

$ du -sh Louisiana_Installer.exe 
1.4G    Louisiana_Installer.exe

$ sha1sum Louisiana_Installer.exe 
a95fe6bce960274e1651c569e00df5a8e0068eac  Louisiana_Installer.exe

Regards

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list