Advice fixing #13683 (DirectX mouse overlay?)

Christopher Thielen christopher at thielen.co
Tue Apr 22 19:57:00 CDT 2014


Thanks Ken!

I don't think a missing library is the problem: the game stores all its 
texture resources in a file called bitmap16.flx and the code paths under 
Wine for reading those bitmaps and making textures out of them seems to 
work just fine given that many of them are visible in the final running 
game.

The offset of the cursor resource within bitmap16.flx is 0x1020eb4 and 
the '.flx item' (as files within this proprietary archive are called) 
itself is about 400,000 bytes (that's for 121 separate cursors all read 
at once).

Looking through +file,+tid,+relay recommended by Ken, I found:

0009:trace:file:CreateFileW L"C:\\GOG Games\\Ultima IX - 
Ascension\\static\\bitmap16.flx" GENERIC_READ  creation 4 attributes 0x80
0009:trace:file:RtlDosPathNameToNtPathName_U (L"C:\\GOG Games\\Ultima IX 
- Ascension\\static\\bitmap16.flx",0x32ef74,(nil),(nil))
0009:trace:file:RtlGetFullPathName_U (L"C:\\GOG Games\\Ultima IX - 
Ascension\\static\\bitmap16.flx" 520 0x32ecc4 (nil))
0009:trace:file:wine_nt_to_unix_file_name L"\\??\\C:\\GOG Games\\Ultima 
IX - Ascension\\static\\bitmap16.flx" -> 
"/home/cthielen/.wine/dosdevices/c:/GOG Games/Ultima IX - 
Ascension/static/bitmap16.flx"
0009:trace:file:CreateFileW returning 0xac



which I believe implies bitmap16.flx is being given the file handle 
0xac. Searching for '0xac' I later find:



0009:Call KERNEL32.SetFilePointer(000000ac,01020eb4,00000000,00000000) 
ret=005de4c9
0009:Ret  KERNEL32.SetFilePointer() retval=01020eb4 ret=005de4c9
0009:Call 
KERNEL32.ReadFile(000000ac,02539110,00061b8c,0032edfc,00000000) ret=005de512
0009:trace:file:ReadFile 0xac 0x2539110 400268 0x32edfc (nil)
0009:Ret  KERNEL32.ReadFile() retval=00000001 ret=005de512
0009:Call KERNEL32.GetLastError() ret=005de518
0009:Ret  KERNEL32.GetLastError() retval=00000002 ret=005de518
0009:Call ntdll.RtlAllocateHeap(01450000,00000000,00001700) ret=00714f22
0009:Ret  ntdll.RtlAllocateHeap() retval=0259aca8 ret=00714f22
0009:Call ntdll.RtlAllocateHeap(01450000,00000000,00000200) ret=00714f22
0009:Ret  ntdll.RtlAllocateHeap() retval=0259c3b0 ret=00714f22
0009:Call user32.LoadCursorA(00000000,00007f00) ret=005d5743
0009:Ret  user32.LoadCursorA() retval=00010038 ret=005d5743
0009:Call user32.SetCursor(00010038) ret=005dbf5f
0009:Call winex11.drv.SetCursor(00010038) ret=7eb0f777
0009:Ret  winex11.drv.SetCursor() retval=00000000 ret=7eb0f777
0009:Ret  user32.SetCursor() retval=00000000 ret=005dbf5f
0009:Call user32.CreateWindowExA(00000000,0032f5c0 
"OFCBlackWindowClass",00787774 "Ultima 
IX",80030000,80000000,80000000,80000000,80000000,00000000,00000000,00400000,00000000) 
ret=005d579c
0009:Call KERNEL32.LZOpenFileW(0032ee74 L"C:\\GOG Games\\Ultima IX - 
Ascension\\u9.exe",0032ed64,00000000) ret=b7788b42
0009:trace:file:LZOpenFileA (C:\GOG Games\Ultima IX - 
Ascension\u9.exe,0x32ed64,0)


which appears to be reading the exact offset I know the cursor to be in 
within bitmap16.flx (file handle 0xac presumably). It also seems to 
request about 400,000 bytes at that offset, which also lines up with 
what I know about the missing cursor resource.

What it then seems to do is call LoadCursor and SetCursor which may be 
curious because I thought we had ruled out user32 cursors as having been 
used. Based on cross-compiling d3d7 and running the game on Windows XP 
with Wine's d3d7 however, we know the problem is not in Wine's D3D 
implementation, so maybe it's logical to suspect cursor after all.

However that doesn't make much sense because LoadCursor 7f00 is the 
standard system cursor.

But what about the GetLastError() call returning 2 (which I believe is 
ERROR_FILE_NOT_FOUND)? Does that seem normal right after a successful 
(non-zero) file read?

Here's a wild theory knowing little about this stuff: ReadFile is maybe 
supposed to clear out that thread's GetLastError value and u9.exe is 
calling GetLastError() to see if errors exist, instead of checking only 
after a zero return value from ReadFile like it should (it is considered 
a poorly written game). If Wine doesn't clear out GetLastError 
correctly, it could cause an alternate code path to run under Wine in 
which the cursors are believed not to be loaded properly.

Notably, that same file handle seems to be used correctly later on:

(0xac is bitmap16.flx)

0009:Call KERNEL32.SetFilePointer(000000ac,01e3dcc0,00000000,00000000) 
ret=005de4c9
0009:Ret  KERNEL32.SetFilePointer() retval=01e3dcc0 ret=005de4c9
0009:Call 
KERNEL32.ReadFile(000000ac,0032f3f4,00000008,0032f3c4,00000000) ret=005de512
0009:trace:file:ReadFile 0xac 0x32f3f4 8 0x32f3c4 (nil)
0009:Ret  KERNEL32.ReadFile() retval=00000001 ret=005de512
0009:Call KERNEL32.GetLastError() ret=005de518
0009:Ret  KERNEL32.GetLastError() retval=00000000 ret=005de518

Or is that am incorrect assumption?

Any ideas?

On 03/24/2014 06:27 PM, Ken Thomases wrote:
> On Mar 24, 2014, at 7:48 PM, Christopher Thielen wrote:
>
>> Using WINEDEBUG=+all, the resource in question (static/bitmap16.flx) is loaded via kernel32's CreateFile, ReadFile.
>>
>> Is there a way to trace only kernel32 calls dealing with a specific file handle? I'm curious if there are any failed reads. Does that seem like a reasonable next step?
>
> Not really.  You'll want to use a +file log and follow the handle as it's passed to subsequent calls.  It might also be necessary to use +tid,+relay to see all uses if Wine isn't logging the handle in all relevant functions.
>
> Certainly, look for failed reads, but I wouldn't expect that unless you think the file is damaged vs. what's installed on Windows.  More likely, the game requires external help interpreting the data that is has read, like a compression or image library.  If that's not present or is incomplete in Wine, then that would explain the problem.  The +tid,+relay log may help to identify what the program does next after it has read the data in.
>
> -Ken
>



More information about the wine-devel mailing list