Hi everyone,
I've been following Wine development for a while but now I think it's time to contribute something. I don't use Windows anymore (except for PowerPoint at work), but I decided it would be good to be able to play some games on Linux. So I grabbed Wine from CVS, compiled it up and tested some games, with the intention of finding where the problems were and hopefully fixing them. I have put my results on a web page at:
http://www.epcc.ed.ac.uk/~jamesp/wine-games.html
to avoid making this posting even longer. Note that I haven't looked in detail at most of these yet, I just tried them out once to see what would happen. I'm gradually working through the list, debugging them.
I've already submitted one patch (to solve a D3D blend mode problem that affected SonicR). I have traced a number of the other problems to specific aspects of Wine, but I'm not sure how to go about fixing them. Any advice on these points from experienced developers would be welcome:
1. MusicVR exits with this error:
X Error of failed request: GLXBadDrawable Major opcode of failed request: 145 (GLX) Minor opcode of failed request: 11 (X_GLXSwapBuffers) Serial number of failed request: 10522 Current serial number in output stream: 10523
I traced it to the line:
glXMakeCurrent(default_display, None, NULL)
in dlls/opengl32/wgl.c. My OpenGL (nVidia) doesn't seem to like the drawable being set to None, although according to the GLX docs, this should be OK. Simply commenting out the line makes the game work fine, but I don't think this is the right fix. Any ideas?
2. Settlers III crashes almost straight away, in the code of the PE-Crypt protection system. This is caused by the processor's direction flag (which controls whether pointers are incremented or decremented by string instructions) getting reset somewhere, probably in Wine code. Can anyone comment on treatment of this flag in Wine? Is it likely to be clobbered in lots of places? Basically, is there any hope of getting this working? I'm not sure where to start with this one.
3. South Park Rally creates its DirectInput object using the generic OLE functions, which doesn't work in Wine right now. I have some initial code to support this, but not sure if it does everything it needs to. I have:
- copied regsvr.c from the DirectSound DLL and edited it to register the DirectInput classes, and implement the DirectInput Dll[Un]RegisterServer methods
- removed the stubs of those functions from dinput_main.c
- added regsvr.c to the list of source files in dinput's Makefile.in, and added ole32 and advapi32 to the list of imports
It would also be good if the default registry created by winebuild contained the necessary entries to make this work (I had to add them by hand), but I couldn't find where the initial registry entries come from.
If this all sounds OK, I can submit it as a patch. Although even with this support, South Park Rally fails with another DirectX problem. One step at a time though...
4. The CD audio in Sonic 3D doesn't play in Wine yet. I found there were two separate problems causing this. First, it's trying to use CD device 2. No idea where this number comes from, as I have only one CD-ROM in the system, and the game doesn't seem to be specifying device 2 anywhere. Anyone know where mcicda gets the device ID from, save me spending ages looking for it?
Second, it's using TMSF (track,minutes,seconds,frames) format to specify locations on the CD. These appear as colon-separated values in the MCI commands (e.g. "02:00:00") but the argument parser chokes on them, expecting a single integer. I got around this by hacking MCI_GetDWord to recognise the colons and parse these arguments correctly, but maybe that's not the way to do it... any suggestions?
Sorry this post is so long. Finally, I'd just like to say great job everyone! I was impressed that things like DirectX, InstallShield and even SecuROM copy protection are working so well - they're flawless on some of the games I tried. It's really come on since I first tried it back in 2000.
Cheers, James
On Mon, 29 Mar 2004 11:37:46 +0100, James Perry wrote:
I traced it to the line:
glXMakeCurrent(default_display, None, NULL)
in dlls/opengl32/wgl.c. My OpenGL (nVidia) doesn't seem to like the drawable being set to None, although according to the GLX docs, this should be OK. Simply commenting out the line makes the game work fine, but I don't think this is the right fix. Any ideas?
If you could do a non-wine test case for that and see if it's just a buggy driver, that'd be good.
- Settlers III crashes almost straight away, in the
code of the PE-Crypt protection system. This is caused by the processor's direction flag (which controls whether pointers are incremented or decremented by string instructions) getting reset somewhere, probably in Wine code. Can anyone comment on treatment of this flag in Wine? Is it likely to be clobbered in lots of places? Basically, is there any hope of getting this working? I'm not sure where to start with this one.
Good catch! I have not seen any references to this flag in my voyages over the code, so it's possible we are indeed clobbering this flag somewhere - it may even be implicit via gcc. If you can trace the point at which it's being reset we might be able to special case this.
It would also be good if the default registry created by winebuild contained the necessary entries to make this work (I had to add them by hand), but I couldn't find where the initial registry entries come from.
They now come from tools/wine.inf - self registering DLLs should be triggered in this file too on initial setup so no default registry entries are needed.
If this all sounds OK, I can submit it as a patch.
Yes, it does but mark the DLL as self registering in wine.inf first.
- The CD audio in Sonic 3D doesn't play in Wine yet. I
found there were two separate problems causing this. First, it's trying to use CD device 2. No idea where this number comes from, as I have only one CD-ROM in the system, and the game doesn't seem to be specifying device 2 anywhere. Anyone know where mcicda gets the device ID from, save me spending ages looking for it?
Try the "Device" line in the config file - with Wine CVS this might be ignored, can't remember, in which case it could be a regression? DOS devices were recently changed to use symlinks and stuff....
Sorry this post is so long. Finally, I'd just like to say great job everyone! I was impressed that things like DirectX, InstallShield and even SecuROM copy protection are working so well - they're flawless on some of the games I tried. It's really come on since I first tried it back in 2000.
No problem, you sound like you know what you're doing. When in doubt, submit a patch and see what people say. Good to have you on board!
thanks -mike
Thanks for the responses, and sorry for the late reply (real life has been limiting my hacking time...)
glXMakeCurrent(default_display, None, NULL)
If you could do a non-wine test case for that and see if it's just a buggy driver, that'd be good.
It turns out not to be as simple as that. I did a +opengl trace and the game makes the same call without any problem several times before the crash. So it must be something to do with the context whether it crashes or not.
Good catch! I have not seen any references to this flag in my voyages over the code, so it's possible we are indeed clobbering this flag somewhere - it may even be implicit via gcc. If you can trace the point at which it's being reset we might be able to special case this.
It's difficult to trace properly as PECrypt has debugger detection and behaves oddly if it detects breakpoints or whatever. But I narrowed it down to 3 Wine calls in the critical loop: SetEvent, WaitForSingleObject and ResetEvent. I tried wrapping each of these functions with __asm__("pushfl\n"); at the start and __asm__("popfl\n"); at the end to preserve the flags - with this, PECrypt works fine and the game gets as far as trying to initialise DirectX. Not exactly a neat fix though.
I never did trace exactly where the flag was getting clobbered, but I disassembled some basic libc functions and found that memcpy and memset both clear the direction flag. So it could be happening almost anywhere - looks like it is standard practise in UNIX to clobber this flag.
Cheers, James
On Tue, 06 Apr 2004 09:23:45 +0100, James Perry wrote:
It's difficult to trace properly as PECrypt has debugger detection and behaves oddly if it detects breakpoints or whatever. But I narrowed it down to 3 Wine calls in the critical loop: SetEvent, WaitForSingleObject and ResetEvent. I tried wrapping each of these functions with __asm__("pushfl\n"); at the start and __asm__("popfl\n"); at the end to preserve the flags - with this, PECrypt works fine and the game gets as far as trying to initialise DirectX. Not exactly a neat fix though.
Did you have to do all of them, or is it just one function that needs this treatment? Are you sure it's not that we need to set the flag before jumping to the entrypoint? PECrypt sounds like it should run very early on in the programs lifetime: how much stuff does it do before hitting this bug?
I never did trace exactly where the flag was getting clobbered, but I disassembled some basic libc functions and found that memcpy and memset both clear the direction flag. So it could be happening almost anywhere - looks like it is standard practise in UNIX to clobber this flag.
I wouldn't say standard practice in UNIX, more just a quirk of the GNU implementations. If there is really widespread software that depends on this behaviour though there is precedent for including a hack for it - see the DllMain wrapper which preserves %ebx for an example.
thanks -mike
On Tue, Apr 06, 2004 at 09:23:45AM +0100, James Perry wrote:
Thanks for the responses, and sorry for the late reply (real life has been limiting my hacking time...)
glXMakeCurrent(default_display, None, NULL)
If you could do a non-wine test case for that and see if it's just a buggy driver, that'd be good.
It turns out not to be as simple as that. I did a +opengl trace and the game makes the same call without any problem several times before the crash. So it must be something to do with the context whether it crashes or not.
Good catch! I have not seen any references to this flag in my voyages over the code, so it's possible we are indeed clobbering this flag somewhere - it may even be implicit via gcc. If you can trace the point at which it's being reset we might be able to special case this.
It's difficult to trace properly as PECrypt has debugger detection and behaves oddly if it detects breakpoints or whatever. But I narrowed it down to 3 Wine calls in the critical loop: SetEvent, WaitForSingleObject and ResetEvent. I tried wrapping each of these functions with __asm__("pushfl\n"); at the start and __asm__("popfl\n"); at the end to preserve the flags - with this, PECrypt works fine and the game gets as far as trying to initialise DirectX. Not exactly a neat fix though.
I had a similar experience 2 years ago or, I think it was either Set or ResetEvent.
If this is need we can generate an assembler wrapper around the function which just saves the flags or similar.
Or do some save_flags() / restore_flags() magic.
Ciao, Marcus
- MusicVR exits with this error:
X Error of failed request: GLXBadDrawable Major opcode of failed request: 145 (GLX) Minor opcode of failed request: 11 (X_GLXSwapBuffers) Serial number of failed request: 10522 Current serial number in output stream: 10523
I traced it to the line:
Could you send me a +opengl trace of the problem ? Maybe the game is done some strange things (like doing a SwapBuffer without a rendering context set or stuff like that) which are OK on Windows and not on Linux.
As for your Dungeon Keeper II problem, see a recent thread for a hint to get it running (it seems you need to do 'wine X:\y\z\app.exe' for it to run - i.e. to give it a fully qualified path and not any relative path). At least it worked with Dungeon Keeper I (that reminds me I still have a patch to resend to AJ :-) ).
Anyway, thanks for using Wine on games... It's nice to see some people are actually using that code :-)
Lionel
- MusicVR exits with this error:
Could you send me a +opengl trace of the problem ? Maybe the game is done some strange things (like doing a SwapBuffer without a rendering context set or stuff like that) which are OK on Windows and not on Linux.
I did the +opengl trace, but it comes to about 16MB! Is there something specific you are looking for that I could grep for?
As for your Dungeon Keeper II problem, see a recent thread for a hint to get it running (it seems you need to do 'wine X:\y\z\app.exe' for it to run - i.e. to give it a fully qualified path and not any relative path). At least it worked with Dungeon Keeper I (that reminds me I still have a patch to resend to AJ :-) ).
Thanks, it seems to get a bit further if I run it that way - looks like it's drawing something and some mci fixmes come up before it exits.
Anyway, thanks for using Wine on games... It's nice to see some people are actually using that code :-)
Thank you for writing that code!
Cheers, James
On Tue, 06 Apr 2004 09:29:05 +0100, James Perry wrote:
I did the +opengl trace, but it comes to about 16MB! Is there something specific you are looking for that I could grep for?
bzip2 destroys Wine traces. 16mb is nothing compared to the multi-gig logs we sometimes deal with around here ;)
Mike Hearn wrote:
On Tue, 06 Apr 2004 09:29:05 +0100, James Perry wrote:
I did the +opengl trace, but it comes to about 16MB! Is there something specific you are looking for that I could grep for?
bzip2 destroys Wine traces. 16mb is nothing compared to the multi-gig logs we sometimes deal with around here ;)
Where is 'here'?
btw, are there already any automated tools for parsing Wine logs? I mean no matter how much people hate the talkback built into Windows XP, I'd love to have such a thing enabled on Wine if it would help (aka, be automaticly processed and statistics put up).
Henk Poley <><
I did the +opengl trace, but it comes to about 16MB! Is there something specific you are looking for that I could grep for?
As Mike said, Wine traces compress REALLY well with gzip or bzip2. After, once it gets into a manageable state, you could either upload it somewhere for me to download it or you could sent it to my bbrox@bbrox.org email address.
Another possibility is to create a bug on Bugzilla and to attach the trace there (this is, after all, what Bugzilla is there for) :-)
Lionel
Lionel Ulmer wrote:
I did the +opengl trace, but it comes to about 16MB! Is there something specific you are looking for that I could grep for?
As Mike said, Wine traces compress REALLY well with gzip or bzip2. After, once it gets into a manageable state, you could either upload it somewhere for me to download it or you could sent it to my bbrox@bbrox.org email address.
OK, thanks for the suggestions. It's online now at
http://www.epcc.ed.ac.uk/~jamesp/gltrace.txt.bz2
only 103k.
Cheers, James
On Wed, Apr 07, 2004 at 10:09:30AM +0100, James Perry wrote:
OK, thanks for the suggestions. It's online now at
From what I can see, the culprit would be this :
trace:opengl:X11DRV_SwapBuffers (0x403d55e0) trace:opengl:wglMakeCurrent ((nil),(nil)) X Error of failed request: GLXBadDrawable
As the glXSwapBuffers call may return before the buffer swap is actually done in hardware, it may happen that the driver does not handle properly an application which unsets the current context before the actual swap is done in the background.
Could you try to see if the attached 'hack' fixes the issue ? If yes, this may be a bug in NVIDIA's GL drivers, if not, we will need to investigate a bit more :-)
Lionel
From what I can see, the culprit would be this :
trace:opengl:X11DRV_SwapBuffers (0x403d55e0) trace:opengl:wglMakeCurrent ((nil),(nil)) X Error of failed request: GLXBadDrawable
As the glXSwapBuffers call may return before the buffer swap is actually done in hardware, it may happen that the driver does not handle properly an application which unsets the current context before the actual swap is done in the background.
Could you try to see if the attached 'hack' fixes the issue ? If yes, this may be a bug in NVIDIA's GL drivers, if not, we will need to investigate a bit more :-)
Thanks for that Lionel - unfortunately it's still doing the same thing even with your patch. I'm not sure what to try next...
Cheers, James