Advice fixing #13683 (DirectX mouse overlay?)

Christopher Thielen christopher at thielen.co
Wed Apr 23 02:15:45 CDT 2014


Sadly didn't help.

I discovered API Monitor for Windows so I've been comparing the two code 
paths as best I can. They're pretty similar between Windows XP and Wine. 
My theory about clearing LastError wasn't correct - Windows XP also 
leaves it with stale error codes.

Once the cursor data is loaded from bitmap16.flx to a heap, I never see 
a reference to that memory again, at least in an API trace. After 
various initializations, there are a lot of CreateTexture calls followed 
by LockRect ... UnlockRect. From reading around online, my guess is the 
game uploads textures using memcpy() while the rect is locked. Can 
anyone who knows a bit more about D3D confirm that's a probable method 
of uploading textures?

If that's true, I think the next logical step is trying to find when the 
texture resource is loaded in the Windows code path so I can start to 
find where Wine differs. I'm not sure how to do that short of API 
Monitor's "break on call and look at assembly" feature.

On 4/22/2014 5:57 PM, Christopher Thielen wrote:
> 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