http://bugs.winehq.org/show_bug.cgi?id=34268
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download Status|UNCONFIRMED |NEW URL| |http://www.atomicgamer.com/ | |files/101304/louisiana-adve | |nture-demo CC| |focht@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@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/1099bb5e76de05718e3cbd43a3d032688...
--- 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/edb01d2662748125b7ef7d9a1dc21419e...
--- 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@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@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@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIPBDI@Z(0032f1e8,0423fbe8 ".",ffffffff) ret=0423809b ... 0025:Ret msvcp71.?rfind@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIPBDI@Z() retval=0000005d ret=0423809b 0025:Call msvcp71.?rfind@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIPBDI@Z(0032f1e8,0423fbe4 "\",ffffffff) ret=042380b3 ... 0025:Ret msvcp71.?rfind@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIPBDI@Z() retval=00000051 ret=042380b3 0025:Call msvcp71.?rfind@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEIPBDI@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