Hello, In the latest version of wine (0.9.16) there is a regression which makes Dune 2000 crash. After some debugging i found that the problem lays in IDirectDrawSurfaceImpl_Release method. The game (Dune 2000) shows that the assumption that all attached surfaces should be destroyed regardless of their refcount is wrong.
What causes the crash in few words: - first Dune 2000 creates a surface with a backbuffer - then it gets the backbuffer interface by GetAttachedSurface method (refcount for the backbuffer is incremented) - it releases the frontbuffer (the backbuffer is destroyed even though its refcount is higher than frontbuffer's) - creates new frontbuffer and an offscreen plain - when one starts a mission the game tries to use the old backbuffer (which is then destroyed) and causes a page fault
So my fix is rather quick and thus i'm not quite sure if it's correct. That's because the game works with it but when it quits it leaves the backbuffer not released. I don't know if it's the game's fault or the fix has to be done some other way. I've done it this way:
--- surface.c 26 Jun 2006 12:15:20 -0000 1.6 +++ surface.c 29 Jun 2006 14:09:59 -0000 @@ -377,7 +377,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDr while( (surf = This->next_complex) ) { This->next_complex = surf->next_complex; /* Unchain it from the complex listing */ - IDirectDrawSurfaceImpl_Destroy(surf); /* Destroy it */ + IDirectDrawSurfaceImpl_Release(surf); /* Release it */ }
If you (Stefan probably) need more info about the bug i can provide some logs
Krzysiek
Am Donnerstag 29 Juni 2006 16:43 schrieb Krzysztof Benkowski:
Hello, In the latest version of wine (0.9.16) there is a regression which makes Dune 2000 crash. After some debugging i found that the problem lays in IDirectDrawSurfaceImpl_Release method. The game (Dune 2000) shows that the assumption that all attached surfaces should be destroyed regardless of their refcount is wrong.
According to the msdn this should happen, and it sounds logical to me. All complex surfaces are created with one call, so they should be destroyed with one call too.
I haven't seen a single app explicitly releasing the back buffer, even the sdk demos don't do that. Ideally a test case could be of help, but I don't know how to test if a surface is actually destroyed.
What causes the crash in few words:
- first Dune 2000 creates a surface with a backbuffer
- then it gets the backbuffer interface by GetAttachedSurface method
(refcount for the backbuffer is incremented)
- it releases the frontbuffer (the backbuffer is destroyed even though
its refcount is higher than frontbuffer's)
Are you sure that the front buffer is meant to be destroyed? Maybe the front buffer's refcount is meant to be increased somewhere, so it isn't destroyed?
- creates new frontbuffer and an offscreen plain
Does it attach the front buffer to the back buffer, or vice versa?
So my fix is rather quick and thus i'm not quite sure if it's correct. That's because the game works with it but when it quits it leaves the backbuffer not released. I don't know if it's the game's fault or the fix has to be done some other way. I've done it this way:
--- surface.c 26 Jun 2006 12:15:20 -0000 1.6 +++ surface.c 29 Jun 2006 14:09:59 -0000 @@ -377,7 +377,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDr while( (surf = This->next_complex) ) { This->next_complex = surf->next_complex; /* Unchain it from the complex listing */
IDirectDrawSurfaceImpl_Destroy(surf); /* Destroy it */
IDirectDrawSurfaceImpl_Release(surf); /* Release it */ }
This was my original way of handling this, and it lead to huge memory leaks in 3D games which create mipmap textures. Usually they call getAttachedSurface for the sublevels and didn't care to release the surfaces.
If someone can think of a way to prove that a COM object is actually destroyed then a test case might clear up this issue.
Stefan
On 29/06/06, Stefan Dösinger stefandoesinger@gmx.at wrote:
If someone can think of a way to prove that a COM object is actually destroyed then a test case might clear up this issue.
Stefan
Do an AddRef() and hope the memory wasn't overwritten yet? :-)
Am Donnerstag 29 Juni 2006 16:43 schrieb Krzysztof Benkowski:
Hello, In the latest version of wine (0.9.16) there is a regression which makes Dune 2000 crash. After some debugging i found that the problem lays in IDirectDrawSurfaceImpl_Release method. The game (Dune 2000) shows that the assumption that all attached surfaces should be destroyed regardless of their refcount is wrong.
After a long google session I found a downloadable demo, but I can't reproduce the bug. The game starts fine and I can play just fine. The game doesn't clean up properly, it doesn't release the front buffer(stays at refcount 1), and of course the back buffer is left with refcount 2. The cleanup code in dllMain releases both surfaces and the directdraw interface.
I noticed that 8 bit graphics do not work.
Can you make sure that you have updated to the latest git code and mail me a +ddraw trace if the problem still occurs?
Stefan
On Thu, Jun 29, 2006 at 04:43:04PM +0200, Krzysztof Benkowski wrote:
--- surface.c 26 Jun 2006 12:15:20 -0000 1.6 +++ surface.c 29 Jun 2006 14:09:59 -0000 @@ -377,7 +377,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDr while( (surf = This->next_complex) ) { This->next_complex = surf->next_complex; /* Unchain it from the complex listing */
IDirectDrawSurfaceImpl_Destroy(surf); /* Destroy it */
IDirectDrawSurfaceImpl_Release(surf); /* Release it */ }
as this seems already solved just for the files. this fix let Planescape Torment crash (before it just ended silently by releasing its "primary state block") - it worked before the ddraw patches white fine. i will soon file a bugreport and provide a link to the demo.
Hi,
as this seems already solved just for the files. this fix let Planescape Torment crash (before it just ended silently by releasing its "primary state block") - it worked before the ddraw patches white fine. i will soon file a bugreport and provide a link to the demo.
Can you also attach a +ddraw,+d3d7 trace? Preferably with and without the hack? There is a demo of this game? I have only seen some demo movies, no playable demo :-(
Stefan