VOGONS


First post, by vedmysh

User metadata
Rank Newbie
Rank
Newbie

I am using latest build (atm 2.62.1) to debug a D3D7 application.
It calls DirectDrawCreateEx twice. First time it use NULL as a first parameter (GUID*) and its fine. But next time it calls method with wierd {67685559-3106-11d0-b971-00aa00342f9f}.
This cause dgVoodoo to fail with error:
[dgVoodoo] ERROR: DirectDraw (0B5C52F0) Initialization failed: Invalid device GUID is specified for device creation. Device not found with GUID = {}
[dgVoodoo] ERROR: DirectDrawCreate/DirectDrawCreateEx: creating DirectDraw object has failed.
I searched the internet for this GUID. Looks like its some predefined value for current display adapter (or sort of).

For example in the ReactOS source code we have a comment:
/* 0x0030 */ GUID DisplayGuid; /*? Always {67685559-3106-11D0-B971-00AA00342F9F} ? */
Also its mentioned in some WINE sources too.

Can dgVoodoo also support this "feature" and take in account this value?

Reply 1 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie

In addition. One more small feature request.
Is it possible to have in "debug build" of dgVoodoo more detailed output for Create* functions.

For example:
[dgVoodoo] ERROR: DirectDraw (0B89E4C0)::CreateSurface: creating surface has failed, DDERR_INVALIDCAPS

Its really would be nice to have some explanation which parameter in CreateSurface was offending. Of course, if you manually check parameters then form return code and not redirect HRESULT from the API used.

Reply 2 of 21, by Dege

User metadata
Rank l33t
Rank
l33t

GUID 67685559-3106-11D0-B971-00AA00342F9F seems to be the hardcoded guid of the first device in MS DDraw.

The game you're debugging is probably kind of badly coded. Instead of getting the right guid from DirectDrawEnumerate, it just exploits the fact (for a single display system) that it is always 67685559-3106-11D0-B971-00AA00342F9F and calls into DDrawCreate directly with that.

Anyway, I changed the first 2 of my guids to match MS ones, to fix this incompatibility problem.

vedmysh wrote:

Its really would be nice to have some explanation which parameter in CreateSurface was offending. Of course, if you manually check parameters then form return code and not redirect HRESULT from the API used.

Ok, I can add more explanation messages into that.
Btw, DDERR_INVALIDCAPS means the incoming DDSCAPS2 member of the surface descriptor contains invalid (combination of) cap bits set (say, exclusive flags DDSCAPS_SYSTEMMEMORY and DDSCAPS_VIDEOMEMORY are both set, or sg like this).

Reply 3 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie
Dege wrote:

The game you're debugging is probably kind of badly coded.

Its terribly coded. Mix of win32 and mfc in one application (3 windows - 2 mfc+1 win32, win32 for rendering, one of the mfc transparent for input reading) some hardcoded stuff (as you already noticed).

Dege wrote:

Anyway, I changed the first 2 of my guids to match MS ones, to fix this incompatibility problem.

Great! Thanks.

Dege wrote:

Ok, I can add more explanation messages into that.

Appreciate! Thanks in adavance!

Dege wrote:

Btw, DDERR_INVALIDCAPS means the incoming DDSCAPS2 member of the surface descriptor contains invalid (combination of) cap bits set (say, exclusive flags DDSCAPS_SYSTEMMEMORY and DDSCAPS_VIDEOMEMORY are both set, or sg like this).

Yeah, i understand this. Long time ago i wrote directdraw applications. But its better to read wrapper validation result as text if its possible, because it already did the job.

Reply 4 of 21, by Dege

User metadata
Rank l33t
Rank
l33t

I whipped up a version with the modified guids and the extended debug info on ddraw create methods. The 32 bit version of the DX dlls:

http://dege.fw.hu/temp/ddraw_dbg.zip

Please let me know if something additional is needed to be included or fixed.

Reply 7 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie

Got a question on this build. Got an error:
[dgVoodoo] ERROR: DDBase (0CF9B638): Cannot initialize the DDI object.

What does this error means? An applications creates DDraw several times. The last one lead to that error.
DirectDrawCreateEx parameters was: (lpGuid = 00000000, lplpDD = (some ptr), iid = {15e65ec0-3b9c-11d2-b92f-00609797ea5b}, pUnkOuter = 00000000)

Reply 8 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie

One more issue:

IDirectDraw7::CreateSurface
with
DDSD_BACKBUFFERCOUNT | DDSD_CAPS
DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY

leads to:

[dgVoodoo] ERROR: DirectDraw (0BDB9848)::CreateSurface: Invalid caps flags for a plain offscreen surface. None of the following flags can be specified for that: DDSCAPS_MIPMAP, DDSCAPS_COMPLEX, DDSCAPS_FLIP, DDSCAPS_OPTIMIZED.

Is this correct?

For example this is from DX SDK7 manual (Creating Complex Surfaces and Flipping Chains):

The following example shows how to prepare for creating a primary surface flipping chain. […]
Show full quote

The following example shows how to prepare for creating a primary surface flipping chain.

DDSURFACEDESC2 ddsd2;
ddsd2.dwSize = sizeof(ddsd2);

// Tell DirectDraw which members are valid.
ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

// Request a primary surface with a single
// back buffer
ddsd2.ddsCaps.dwCaps = DDSCAPS_COMPLEX | DDSCAPS_FLIP |
DDSCAPS_PRIMARYSURFACE;
ddsd2.dwBackBufferCount = 1;
The previous example constructs a double-buffered flipping environment—a single call to the IDirectDrawSurface7::Flip method exchanges the surface memory of the primary surface and the back buffer. If you specify 2 for the value of the dwBackBufferCount member of the DDSURFACEDESC2 structure, two back buffers are created, and each call to Flip rotates the surfaces in a circular pattern, providing a triple-buffered flipping environment. For more information, see Flipping Surfaces.

...

Well. Looks like this is correct error. Just tested this flags combination in DX SDK7 Ddraw Test application and got DDERR_INVALIDPARAMS. At least modern DDraw implementations works this way.

Reply 9 of 21, by Dege

User metadata
Rank l33t
Rank
l33t
vedmysh wrote:
Got a question on this build. Got an error: [dgVoodoo] ERROR: DDBase (0CF9B638): Cannot initialize the DDI object. […]
Show full quote

Got a question on this build. Got an error:
[dgVoodoo] ERROR: DDBase (0CF9B638): Cannot initialize the DDI object.

What does this error means? An applications creates DDraw several times. The last one lead to that error.
DirectDrawCreateEx parameters was: (lpGuid = 00000000, lplpDD = (some ptr), iid = {15e65ec0-3b9c-11d2-b92f-00609797ea5b}, pUnkOuter = 00000000)

A backend object containing D3D11 impl couldn't be created. I think you should enable the D3D11 debug layer (part of the Win SDK) to find out more about that.

vedmysh wrote:
IDirectDraw7::CreateSurfacewith DDSD_BACKBUFFERCOUNT | DDSD_CAPS DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRI […]
Show full quote

IDirectDraw7::CreateSurfacewith
DDSD_BACKBUFFERCOUNT | DDSD_CAPS
DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY
leads to:
[dgVoodoo] ERROR: DirectDraw (0BDB9848)::CreateSurface: Invalid caps flags for a plain offscreen surface. None of the following flags can be specified for that: DDSCAPS_MIPMAP, DDSCAPS_COMPLEX, DDSCAPS_FLIP, DDSCAPS_OPTIMIZED.

Are you sure? That's a perfectly valid cap flag combination, describing a primary surface. I gave it a go in my test app

DDSURFACEDESC2 ddesc;
ZeroMemory (&ddesc, sizeof (ddesc));
ddesc.dwSize = sizeof (ddesc);

ddesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE;
ddesc.dwBackBufferCount = 1;

lpDD4->CreateSurface (&ddesc, &lpPrimSurface, NULL);

and it succeeds:

Surface created 045C8418, 2560x1440
flags:DDSD_CAPS, DDSD_HEIGHT, DDSD_WIDTH, DDSD_PITCH, DDSD_BACKBUFFERCOUNT, DDSD_PIXELFORMAT,
type:DDSCAPS_COMPLEX, DDSCAPS_FLIP, DDSCAPS_FRONTBUFFER, DDSCAPS_PRIMARYSURFACE, DDSCAPS_3DDEVICE, DDSCAPS_VIDEOMEMORY, DDSCAPS_VISIBLE, DDSCAPS_LOCALVIDMEM,
ID: 1
DirectDrawSurface::QueryInterface (this = 045C8418, riid = {IID_IDirectDrawSurface4}, ppvObject = 008FC264)
DirectDrawSurface: Creating interface: 0394E0C8
interface 0394E0C8 queried
[dgVoodoo] INFO: DirectDraw (01330C80)::CreateSurface: Primary surface as a flipping chain is created, head DirectDrawSurface is (045C8418).

Reply 10 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie

A backend object containing D3D11 impl couldn't be created. I think you should enable the D3D11 debug layer (part of the Win SDK) to find out more about that.

I see. The problem here is this error is floating and not 100% reproducible.

Are you sure? That's a perfectly valid cap flag combination, describing a primary surface. I gave it a go in my test app

Well, I am using dgVoodoo in cooperation with dxWnd. It is possible, that dxWnd under the hood change the flags. But the information about the flags i got from two sources - dxWnd debug messages and rohitab api monitor. I will investigate the problem and let you know if find something usefull.

Also, as i said before this flag combination lead to an error in SDK test tool (on "native" ddraw(ms ddraw.dll) "wrapper" in windows 10). Screenshot attached.

Attachments

  • test.png
    Filename
    test.png
    File size
    78.26 KiB
    Views
    2172 views
    File license
    Fair use/fair dealing exception
Last edited by vedmysh on 2019-10-15, 14:56. Edited 1 time in total.

Reply 12 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie

Are you sure? That's a perfectly valid cap flag combination, describing a primary surface. I gave it a go in my test app

Confirmed - the root of the problem is in the dxwnd. It replaces some parameters later and then call dgVoodoo.

Reply 13 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie

My "adventures" continues.
Now i got constant crashes. This looks like some memory corruption or double free (possible at thread exit). Seems offending thread was spawned by dgVoodoo (or, possible, in d3d11 runtime?). The call stack is strange (possibly wrong):

ntdll._RtlpFreeHeapInternal@20+D7 ntdll.RtlFreeHeap+ […]
Show full quote

ntdll._RtlpFreeHeapInternal@20+D7
ntdll.RtlFreeHeap+46
msvcrt._free+69
msvcrt.__freefls@4+43
ntdll.void __stdcall RtlpFlsDataCleanup(struct _RTLP_FLS_CONTEXT *,struct _RTLP_FLS_DATA *,unsigned long)+A8
ntdll._RtlProcessFlsData@8+10
ntdll.LdrShutdownThread+34
ntdll.RtlExitUserThread+4C
kernel32.@BaseThreadInitThunk@12+20
ntdll.__RtlUserThreadStart+2F
ntdll.__RtlUserThreadStart@8+1B

Here is the debugger log:

... [dgVoodoo] INFO: Reading config from file C:\Tools\dxwnd\dxwnd-dgvoodoo\alt.dll\dgVoodoo.conf. [dgVoodoo] INFO: INI file bas […]
Show full quote

...
[dgVoodoo] INFO: Reading config from file C:\Tools\dxwnd\dxwnd-dgvoodoo\alt.dll\dgVoodoo.conf.
[dgVoodoo] INFO: INI file based version of config file is successfully read.
DLL loaded: 6A0D0000 C:\Windows\SysWOW64\d3d11.dll
DLL loaded: 58910000 C:\Windows\SysWOW64\D3DCompiler_47.dll
Thread DB08 created, entry: ddraw.6CB2E327 // problematic thread created here, entrypoint in dgVoodoo ddraw module
...
...
...
DirectDraw::SetCooperativeLevel (this = 008E8528, hWnd = 0, dwFlags = 😎 // This happends in main thread
SetCooperativeLevel window: 0, threadId: 56372 // Main thread id
[dgVoodoo] INFO: DirectDraw (008E8528)::SetCooperativeLevel: cooperative level is bound to window (0), normal level
[dgVoodoo] INFO: DirectDraw (008E8528) is released. // Last message before crash

Ddraw.dll imagebase is 6CB00000, disassembly at 6cb2e327:

6CB2E327 | 55 | push ebp | 6CB2E328 | 8BEC […]
Show full quote

6CB2E327 | 55 | push ebp |
6CB2E328 | 8BEC | mov ebp,esp |
6CB2E32A | 56 | push esi |
6CB2E32B | 8B75 08 | mov esi,dword ptr ss:[ebp+8] |
6CB2E32E | 807E 35 00 | cmp byte ptr ds:[esi+35],0 |
6CB2E332 | 0F85 95000000 | jne ddraw.6CB2E3CD |
6CB2E338 | 53 | push ebx |
6CB2E339 | 57 | push edi |
6CB2E33A | 8D5E 14 | lea ebx,dword ptr ds:[esi+14] |
6CB2E33D | 6A FF | push FFFFFFFF |
6CB2E33F | FF76 10 | push dword ptr ds:[esi+10] |
6CB2E342 | FF15 7C30B36C | call dword ptr ds:[<&_WaitForSingleObject@8>] |
6CB2E348 | EB 63 | jmp ddraw.6CB2E3AD |
6CB2E34A | 807E 34 00 | cmp byte ptr ds:[esi+34],0 |
6CB2E34E | 75 4E | jne ddraw.6CB2E39E |
6CB2E350 | 8D4E 04 | lea ecx,dword ptr ds:[esi+4] |
6CB2E353 | 8B01 | mov eax,dword ptr ds:[ecx] |
6CB2E355 | 51 | push ecx |
6CB2E356 | 8B38 | mov edi,dword ptr ds:[eax] |
6CB2E358 | E8 28020000 | call ddraw.6CB2E585 |
6CB2E35D | 807E 35 00 | cmp byte ptr ds:[esi+35],0 |
6CB2E361 | 75 2D | jne ddraw.6CB2E390 |
6CB2E363 | 897E 2C | mov dword ptr ds:[esi+2C],edi |
6CB2E366 | 8BCF | mov ecx,edi |
6CB2E368 | 8B07 | mov eax,dword ptr ds:[edi] |
6CB2E36A | FF50 08 | call dword ptr ds:[eax+8] |
6CB2E36D | 53 | push ebx |
6CB2E36E | 8946 30 | mov dword ptr ds:[esi+30],eax |
6CB2E371 | FF15 4031B36C | call dword ptr ds:[<&_RtlLeaveCriticalSection@4>] |
6CB2E377 | 8B07 | mov eax,dword ptr ds:[edi] |
6CB2E379 | 8BCF | mov ecx,edi |
6CB2E37B | FF50 04 | call dword ptr ds:[eax+4] |
6CB2E37E | 8B07 | mov eax,dword ptr ds:[edi] |
6CB2E380 | 8BCF | mov ecx,edi |
6CB2E382 | 6A 01 | push 1 |
6CB2E384 | FF10 | call dword ptr ds:[eax] |
6CB2E386 | 8366 2C 00 | and dword ptr ds:[esi+2C],0 |
6CB2E38A | 8366 30 00 | and dword ptr ds:[esi+30],0 |
6CB2E38E | EB 1D | jmp ddraw.6CB2E3AD |
6CB2E390 | 85FF | test edi,edi |
6CB2E392 | 74 20 | je ddraw.6CB2E3B4 |
6CB2E394 | 8B07 | mov eax,dword ptr ds:[edi] |
6CB2E396 | 8BCF | mov ecx,edi |
6CB2E398 | 6A 01 | push 1 |
6CB2E39A | FF10 | call dword ptr ds:[eax] |
6CB2E39C | EB 16 | jmp ddraw.6CB2E3B4 |
6CB2E39E | 53 | push ebx |
6CB2E39F | FF15 4031B36C | call dword ptr ds:[<&_RtlLeaveCriticalSection@4>] |
6CB2E3A5 | 6A 01 | push 1 |
6CB2E3A7 | FF15 2031B36C | call dword ptr ds:[<&_SleepStub@4>] |
6CB2E3AD | 53 | push ebx |
6CB2E3AE | FF15 4431B36C | call dword ptr ds:[<&_RtlEnterCriticalSection@4>] |
6CB2E3B4 | 837E 08 00 | cmp dword ptr ds:[esi+8],0 |
6CB2E3B8 | 77 90 | ja ddraw.6CB2E34A |
6CB2E3BA | 53 | push ebx |
6CB2E3BB | FF15 4031B36C | call dword ptr ds:[<&_RtlLeaveCriticalSection@4>] |
6CB2E3C1 | 807E 35 00 | cmp byte ptr ds:[esi+35],0 |
6CB2E3C5 | 0F84 72FFFFFF | je ddraw.6CB2E33D |
6CB2E3CB | 5F | pop edi |
6CB2E3CC | 5B | pop ebx |
6CB2E3CD | 33C0 | xor eax,eax |
6CB2E3CF | 5E | pop esi |
6CB2E3D0 | 5D | pop ebp |
6CB2E3D1 | C2 0400 | ret 4 |

Guess Sleep(1) will help easily identify the source fragment.

Dege, maybe you have any ideas about this?
May i ask you to include pdb files in your releases?
Thanks in advance.

Reply 14 of 21, by Dege

User metadata
Rank l33t
Rank
l33t
vedmysh wrote:

BTW, this tool (DX7 SDK test application) crashes with dgVoodoo after "connection" (DDraw creation).

Yes, I know. That app fumbles directly for data in DDraw objects, at binary level. So it's not complatible with dgVoodoo. I didn't want to have binary layout compatibility with MS ddraw just because of this app.

vedmysh wrote:

Dege, maybe you have any ideas about this?May i ask you to include pdb files in your releases?

That code is the shader compiler thread(s) which aren't utilized starting from 2.61, it's just there in a waiting state.
For memory corruption, did you try Application Verifier?
Do you have other dgVoodoo module loaded in the process in addition to ddraw?
Pdb files would require a dev release of the dlls (in the dgvoodoo api package).

Reply 15 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie
Dege wrote:

Yes, I know. That app fumbles directly for data in DDraw objects, at binary level. So it's not complatible with dgVoodoo. I didn't want to have binary layout compatibility with MS ddraw just because of this app.

I see.

Dege wrote:
That code is the shader compiler thread(s) which aren't utilized starting from 2.61, it's just there in a waiting state. For mem […]
Show full quote

That code is the shader compiler thread(s) which aren't utilized starting from 2.61, it's just there in a waiting state.
For memory corruption, did you try Application Verifier?
Do you have other dgVoodoo module loaded in the process in addition to ddraw?
Pdb files would require a dev release of the dlls (in the dgvoodoo api package).

Thats strange. I used dll version you post in this thread.
Nope. Never used it (AppVerifier) for this purpose.
D3D9.dll and D3DImm.dll is also loaded into the application address space.
Not sure i understand you correctly. Which compiler do you use for dgVoodoo? Because Visual C++ 2017/2019 (and even the older one versions afair) generate pdb files even for release builds.

Reply 16 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie

Well, with Application verifier (enabled Heap, Leak and Memory) and debugger attached for the this application it die in different place - guess its display mode enumeration:

xpro.0042F533 ddraw.6D94CE01 […]
Show full quote

xpro.0042F533
ddraw.6D94CE01
ddraw.6D948960
ddraw.6D959C9B
dxwnd.long __stdcall extEnumDisplayModes(int,long (__stdcall*)(struct IDirectDraw *

But the resulting log has 0 errors and warning

Reply 17 of 21, by Dege

User metadata
Rank l33t
Rank
l33t

Sorry for the late answer.

vedmysh wrote:

D3D9.dll and D3DImm.dll is also loaded into the application address space.

So, it's an app using ddraw + d3d9 together? Shouldn't be a problem, but what if you remove dg d3d9 and let it load the system one?

vedmysh wrote:

Not sure i understand you correctly. Which compiler do you use for dgVoodoo? Because Visual C++ 2017/2019 (and even the older one versions afair) generate pdb files even for release builds.

Yes, I was ambiguous. Currently I compile it with VS2017 and yes, it can produce stripped pdb files. But regular dgVoodoo dll's are compressed so you can't use them together.

vedmysh wrote:

Well, with Application verifier (enabled Heap, Leak and Memory) and debugger attached for the this application it die in different place - guess its display mode enumeration:

xpro.0042F533 ddraw.6D94CE01 […]
Show full quote

xpro.0042F533
ddraw.6D94CE01
ddraw.6D948960
ddraw.6D959C9B
dxwnd.long __stdcall extEnumDisplayModes(int,long (__stdcall*)(struct IDirectDraw *

But the resulting log has 0 errors and warning

What if you enable only 'classic' resolutions for dgVoodoo? Some old apps are known to crash if too many resolutions are enumerated to them.

Reply 18 of 21, by vedmysh

User metadata
Rank Newbie
Rank
Newbie
Dege wrote:

Sorry for the late answer.
So, it's an app using ddraw + d3d9 together? Shouldn't be a problem, but what if you remove dg d3d9 and let it load the system one?

Its ok. I anyway switched my attention to another application.
Its Direct3D 7 app, but i used dgVoodoo in conjunction with DxWnd (thats the priority topic for me, testing its ability to load custom DX dlls) so at some point its possible it hooks d3d9 too.

Dege wrote:

Yes, I was ambiguous. Currently I compile it with VS2017 and yes, it can produce stripped pdb files. But regular dgVoodoo dll's are compressed so you can't use them together.

I see. Just curious - compression on dgVoodoo binary is for anti debug? Because for example in my case ability to use pdb files will greatly increase debug productivity of the target applications.

Dege wrote:

What if you enable only 'classic' resolutions for dgVoodoo? Some old apps are known to crash if too many resolutions are enumerated to them.

Ill try it, thanks!
BTW, thank you for the advice about AppVerifier. I used gflags tool to turn on 'page heap' for application. Now AppVerifier greatly simplify this process.

Reply 19 of 21, by batterymandark

User metadata
Rank Newbie
Rank
Newbie

Speaking of GUID , this problem seems to be problematic for other games

so Need for speed HP:2 throws an exception 0xC000001D, it also stops before it update rendercaps.ini which contain the ScreenModeIndex, which I assume is because it can't get the correct monitor mode, maybe its not getting the correct GUID??

And the lovely GTR FIA 1, this suffer from not getting the correct GUID , as running in native the GUID are not the same as dgvoodoo dispatch, so maybe a similar GUID glitch is related?

wonder if a GUID selector or something in the control panel could work-around for future issues.?
And i'm running an multi-adapter system , so maybe that crates some new shenanigans