[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