Open Trass3r opened 2 years ago
It always seems to crash inside the movie decoding 65CA50 function even with the -nomovies -level mpd6 -32biteverything
parameters. The logs show a Lock2 prior to that with garbage input:
m_IDirect3DDeviceX::Clear (08A39810)
m_IDirect3DDevice9Ex::Clear (089EBC90)
m_IDirect3DDeviceX::BeginScene (08A39810)
m_IDirect3DDevice9Ex::BeginScene (089EBC90)
m_IDirectDrawSurfaceX::Lock2 (093E9C88){0x64f2e808,1689268,0,1153611423,1688664,1686932,1691196,1995936688,33D9E5CB,{0xfffffffe,0x19c7d0},{0x64f1434e,0x19c6c0},{0x70d3c0,0x793388},{0x65737341,0x6f697472},{0x64656c69,MAKEFOURCC(':', ' ', 'F', 'a'),1698981227,0x65636976,0x423a3a33,0x6e696765,0x6e656353},1634082926,
{{ DDSCAPS_3DDEVICE DDSCAPS_ALLOCONLOAD DDSCAPS_BACKBUFFER DDSCAPS_FRONTBUFFER DDSCAPS_HWCODEC DDSCAPS_LIVEVIDEO DDSCAPS_LOCALVIDMEM DDSCAPS_MODEX DDSCAPS_NONLOCALVIDMEM DDSCAPS_OFFSCREENPLAIN DDSCAPS_PRIMARYSURFACE DDSCAPS_SYSTEMMEMORY DDSCAPS_TEXTURE },0x69772039,0x48206874,0x55534552},807425100},1
m_IDirect3DDevice9Ex::TestCooperativeLevel (089EBC90)0
m_IDirectDrawSurfaceX::CreateD3d9Surface (093E9C88) D3d9 Surface size: 128x128 Format: D3DFMT_A8R8G8B8 dwCaps: 0x1800
m_IDirect3DDevice9Ex::CreateTexture (089EBC90)
Creating interface m_IDirect3DTexture9::m_IDirect3DTexture9 (093F8698)
m_IDirect3DTexture9::LockRect (093F8698)
m_IDirect3DTexture9::LockRect (093F8698)
m_IDirectDrawSurfaceX::Lock2 Error: failed to lock surface texture
Other Lock2
s before that also fail but don't seem to lead to a crash.
m_IDirectDrawX::CreateSurface2 (00A6CEF8){0x1007,1024,768,1690736,0,1690856,16,5992124,0019CC9C,{0x5b858b,0x19cc9c},{0x742090,0x742094},{0x19cce8,0x742070},{0x19cd48,0x742074},{0x40,0,32,0xff0000,0xff00,0xff,0x0},32,{{ DDSCAPS_OFFSCREENPLAIN DDSCAPS_SYSTEMMEMORY },0x0,0x0,0x0},0} 4
m_IDirect3D9Ex::CheckDeviceFormat (00ABAD10)0 1 D3DFMT_X8R8G8B8 0 D3DRTYPE_SURFACE D3DFMT_X8R8G8B8
Creating interface m_IDirectDrawSurfaceX::m_IDirectDrawSurfaceX (09419BF8) converting interface from v4 to v9
m_IDirectDrawSurfaceX::AddRef (09419BF8) v4
m_IDirectDrawSurfaceX::GetSurfaceDesc2 (09419BF8)
m_IDirectDrawSurfaceX::GetSurfaceDesc2 (09419BF8):{0x100f,1024,768,4096,0,1690856,16,0,0019CC9C,{0x5b858b,0x19cc9c},{0x742090,0x742094},{0x19cce8,0x742070},{0x19cd48,0x742074},{0x40,0,32,0xff0000,0xff00,0xff,0x0},32,{{ DDSCAPS_OFFSCREENPLAIN DDSCAPS_SYSTEMMEMORY },0x0,0x0,0x0},0}
m_IDirectDrawSurfaceX::Lock2 (09419BF8){0x0,0,0,0,0,0,0,0,00000000,{0x0,0x0},{0x0,0x0},{0x0,0x0},{0x0,0x0},{0x0,0,0,0x0,0x0,0x0,0x0},0,{{},0x0,0x0,0x0},0},1
m_IDirect3DDevice9Ex::TestCooperativeLevel (08A0AA78)0
m_IDirectDrawSurfaceX::CreateD3d9Surface (09419BF8) D3d9 Surface size: 1024x768 Format: D3DFMT_X8R8G8B8 dwCaps: 0x840
m_IDirect3DDevice9Ex::CreateTexture (08A0AA78)
Creating interface m_IDirect3DTexture9::m_IDirect3DTexture9 (094386E8)
m_IDirect3DTexture9::LockRect (094386E8)
m_IDirect3DTexture9::LockRect (094386E8)
m_IDirectDrawSurfaceX::Lock2 Error: failed to lock surface texture
m_IDirectDrawSurfaceX::Release (09419BF8) v4
m_IDirectDrawSurfaceX::~m_IDirectDrawSurfaceX (09419BF8) deleting interface!
m_IDirectDrawSurfaceX::ReleaseD9Surface Releasing Direct3D9 texture surface
m_IDirect3DTexture9::Release (094386E8)
surfaceTexture->LockRect(0, pLockedRect, pRect, Flags);
with Flags=0 returns D3DERR_INVALIDCALL
.
Textures created with D3DPOOL_DEFAULT are not lockable.
DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN
is not handled properly in CreateD3d9Surface
.
https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dpool#constants
https://gamedev.stackexchange.com/questions/7993/idirect3ddevice9ex-and-d3dpool-managed
Creating interface m_IDirectDrawSurfaceX::m_IDirectDrawSurfaceX (092FE0F8) converting interface from v4 to v9
m_IDirectDrawSurfaceX::AddRef (092FE0F8) v4
m_IDirectDrawSurfaceX::GetSurfaceDesc2 (092FE0F8)
m_IDirectDrawSurfaceX::GetSurfaceDesc2 (092FE0F8):{0x100f,1024,768,4096,0,1690856,16,0,0019CC9C,{0x5b858b,0x19cc9c},{0x742090,0x742094},{0x19cce8,0x742070},{0x19cd48,0x742074},{0x40,0,32,0xff0000,0xff00,0xff,0x0},32,{{ DDSCAPS_OFFSCREENPLAIN DDSCAPS_SYSTEMMEMORY },0x0,0x0,0x0},0}
m_IDirectDrawSurfaceX::Lock2 (092FE0F8){0x0,0,0,0,0,0,0,0,00000000,{0x0,0x0},{0x0,0x0},{0x0,0x0},{0x0,0x0},{0x0,0,0,0x0,0x0,0x0,0x0},0,{{},0x0,0x0,0x0},0},1
m_IDirect3DDevice9Ex::TestCooperativeLevel (08A5BEB0)0
m_IDirectDrawSurfaceX::CreateD3d9Surface (092FE0F8) D3d9 Surface size: 1024x768 Format: D3DFMT_X8R8G8B8 ddsCaps: {{ DDSCAPS_OFFSCREENPLAIN DDSCAPS_SYSTEMMEMORY },0x0,0x0,0x0}
m_IDirect3DDevice9Ex::CreateTexture (08A5BEB0) 1024x768x1 0 D3DFMT_X8R8G8B8 0
Creating interface m_IDirect3DTexture9::m_IDirect3DTexture9 (09317660)
m_IDirect3DTexture9::LockRect (09317660)
m_IDirect3DTexture9::LockRect (09317660)
m_IDirectDrawSurfaceX::Lock2 Error: failed to lock surface texture
m_IDirectDrawSurfaceX::Release (092FE0F8) v4
m_IDirectDrawSurfaceX::~m_IDirectDrawSurfaceX (092FE0F8) deleting interface!
m_IDirectDrawSurfaceX::ReleaseD9Surface Releasing Direct3D9 texture surface
m_IDirect3DTexture9::Release (09317660)
m_IDirectDrawSurfaceX::Blt (08A56508)null 09CE4918 null 16777216 0
m_IDirect3DDevice9Ex::TestCooperativeLevel (08A5BEB0)0
m_IDirectDrawSurfaceX::CreateD3d9Surface (08A56508) D3d9 Surface size: 1024x768 Format: D3DFMT_X8R8G8B8 ddsCaps: {{ DDSCAPS_LOCALVIDMEM DDSCAPS_VIDEOMEMORY },0x0,0x0,0x0}
m_IDirect3DDevice9Ex::CreateTexture (08A5BEB0) 1024x768x1 0 D3DFMT_X8R8G8B8 0
Creating interface m_IDirect3DTexture9::m_IDirect3DTexture9 (093171A0)
m_IDirectDrawSurfaceX::QueryInterface (08A56730) IID_GetInterfaceX
m_IDirect3DDevice9Ex::TestCooperativeLevel (08A5BEB0)0
m_IDirect3DDevice9Ex::TestCooperativeLevel (08A5BEB0)0
m_IDirect3DTexture9::GetSurfaceLevel (09317020)
Creating interface m_IDirect3DSurface9::m_IDirect3DSurface9 (09D20AD8)
m_IDirect3DTexture9::GetSurfaceLevel (093171A0)
Creating interface m_IDirect3DSurface9::m_IDirect3DSurface9 (09D204A8)
D3DXLoadSurfaceFromSurface
m_IDirect3DSurface9::GetDesc (09D204A8)
m_IDirect3DSurface9::GetDesc (09D20AD8)
m_IDirect3DSurface9::GetDevice (09D20AD8)
m_IDirect3DDevice9Ex::AddRef (08A5BEB0)
m_IDirect3DDevice9Ex::StretchRect (08A5BEB0)
m_IDirect3DDevice9Ex::Release (08A5BEB0)
m_IDirect3DSurface9::GetDesc (09D20AD8)
m_IDirect3DSurface9::LockRect (09D20AD8)
m_IDirect3DSurface9::GetDesc (09D20AD8)
m_IDirect3DSurface9::GetDevice (09D20AD8)
m_IDirect3DDevice9Ex::AddRef (08A5BEB0)
m_IDirect3DDevice9Ex::CreateTexture (08A5BEB0) 1024x768x1 0 D3DFMT_X8R8G8B8 2
Yes, I realized this after the change. However, the latest check-in should resolve this issue: 280ba38c49f68353239f0d13cbab0999c602869b
Yeah ok now we're back to the original crash I assume. https://gist.github.com/Trass3r/76463d7fc4d5921c53226773f8b65cc6 I added some more logging: https://github.com/elishacloud/dxwrapper/compare/master...Trass3r:dxwrapper:master
The issue is that this game uses Direct3D and so far I have only started the conversion from Direct3D to Direct3D9. Only a hand full of Direct3D games work so far. But I do have this game and will take a look later.
Note: this game uses the Direct3D version 3 interfaces. So far the only games I have seen work are the ones that use the Direct3D version 7 interfaces.
Yeah I know, on the plus side it doesn't use many D3D features. But it's hard to debug since it crashes deep down in game code when it accesses some surface.
Ok, I put a fix in that solves this first issue. There seems to be some other issue I need to look into though.
Thanks it starts up now (using the -level parameter). I don't see the keeper hand (which I think is drawn in a special way, in a separate step after everything has been rendered) and it only shows the 1024x768 content in the upper left part the screen.
Other peculiarities of DK2 are the GOG patch messing around with draw calls and also having its own config in %APPDATA%\GOG and multiple windows getting created during startup. I guess for example the video rendering was done with an external EA library that creates its own window.
If you set FullscreenWindowMode
to 1
then you can start the game normally and see the intro video. The video is done using IID_IMMDeviceEnumerator, which does not interact well with Direct3D9 when in exclusive fullscreen mode.
"I don't see the keeper hand"
Yes, the menu is also not being seen. I'll need to figure out why these items are not being seen. Also, the display looks wrong as it only appears in the upper left corner of the screen:
[Compatibility]
Dd7to9 = 1
[Dd7to9]
DdrawOverrideWidth = 640
DdrawOverrideHeight = 480
[d3d9]
FullscreenWindowMode = 1
This does not solve the invisible menu and hand, but otherwise makes everything work.
It looks like the game play is in 800x600 but the menu is 640x480. I put a fix in that allows ddraw to get the correct resolution so you don't need to use DdrawOverrideWidth/Height.
Yeah they are using different resolutions.
And as I said the GOG patch also fiddles around with those things, e.g. via ScaleMode: https://www.gog.com/forum/dungeon_keeper_series/dk2_gog_configini_extra_settings/post2
It might have to do with the viewport. The structures changed in v5 and v7.
And as I said the GOG patch also fiddles around with those things, e.g. via ScaleMode:
After converting it to Direct3D9 we already have many of those types of options: antialiasing, anisotropic filtering, vertical sync, etc. I tried the Direct3D9 antialiasing and it looks pretty good with this game, IMHO.
It might have to do with the viewport. The structures changed in v5 and v7.
There is already code in there to convert the viewport back and forth between the two structures. I know the code works on this game because the same code is used for ConvertToDirectDraw7
/ConvertToDirect3D7
, which works fine with this game.
Anyways, I am not too worried about the resolution and scaling. I can use the surface size to determine the resolution since this game never calls the SetDisplayMode()
function.
The real question is why the hand and the menu items on the first screen after the intro video are missing.
It's unfortunate RenderDoc doesn't support DX9. When trying other wrappers like dgVoodoo I think the hand part always showed up weirdly as its own frame. ApiTrace shows all the 3D draw calls, then an EndScene, a few Blts and a SetColorKey (maybe a transparency issue?) a WaitForVerticalBlank, multiple Blt's and the finally the Clear2 and new BeginScene.
It's unfortunate RenderDoc doesn't support DX9.
I always use Microsoft PIX for this. You can trace it call-by-call and see the visual display.
ApiTrace shows all the 3D draw calls, then an EndScene, a few Blts and a SetColorKey (maybe a transparency issue?) a WaitForVerticalBlank, multiple Blt's and the finally the Clear2 and new BeginScene.
Yeah, it is weird that there are so many things outside of the BeginScene()
and EndScene()
pair. Using PIX I can see the hand and the menu items in a surface texture. It could be a color key issue.
Thanks for the PIX link. The game doesn't start though. It hangs in the first Present(NULL, NULL, NULL, NULL)
.
The D3D backend was something they only added after the fact. That's why they are still using their SW renderer for T&L, just sending D3DFVF_XYZRHW vertices to be rasterized.
Ok, I see what is happening here. This game is mixing 2D and 3D graphics. However, dxwrapper only supports pure 2D or pure 3D modes. Once the intro video ends it switches to 3D mode. All of the graphics you see are 3D. All of the graphics you don't see are the 2D graphics.
All of the missing graphics are on the primary surface. To fix this we would need to find a way to show the primary surface on top of the scene before calling EndScene()
and Present()
.
With FullscreenWindowMode it works quite well now. It does mess with my desktop resolution though, setting it to 1024x768. The GOG patch handles this by rendering to a surface I think and upscaling it to the desktop resolution.
Once the intro video ends it switches to 3D mode.
Yes the main menu is actually a map.
The movies can be skipped with -nomovies
or -level mpd6
btw, good for debugging.
And there's a reimplementation of the GOG patch for your reference if needed: https://github.com/DiaLight/Ember/blob/b2611b3b65d810299e66d21a693c4b314d67dc9b/patches/gog_patch_dll/fake/FakeDirectDraw1.cpp#L287
ScaleMode handling: https://github.com/DiaLight/Ember/blob/b2611b3b65d810299e66d21a693c4b314d67dc9b/patches/gog_patch_dll/gog_fake.cpp#L80
I put a hack into the module under the DDraw-2D-3D-Mix branch that allows the menu and hand to be seen.
However, this exposes another issue where dxwrapper is not detecting the correct buffer size. If you manually put the correct size into DdrawOverrideWidth/Height then it works for the most part.
I'm not quite sure how to detect the correct display size at this point.
I put a few fixes in for this game. The overlay is now showing up correctly in both the menu and the game play. There are still a few graphical anomalies, especially during the videos. But it should be completely playable at this point.
Here is the build with the fixes in it: dxwrapper.zip
It requires the following settings:
[Compatibility]
Dd7to9 = 1
[Dd7to9]
DdrawOverridePrimaryWidth = 640
DdrawOverridePrimaryHeight = 480
[d3d9]
FullscreenWindowMode = 1
Note: if you are starting the game using the level hack then you may need to adjust the size to something else, like this:
[Dd7to9]
DdrawOverridePrimaryWidth = 800
DdrawOverridePrimaryHeight = 600
Thanks! No need to make the videos perfect. I always use -nomovies
or -level
.
Unfortunately can't test atm. Some definitions conflict with the Win 10/11 SDK d3dcommon.h: https://github.com/elishacloud/dxwrapper/blob/master/Libraries/d3dx9.h#L58 and https://github.com/elishacloud/dxwrapper/blob/master/Libraries/d3dx9.h#L76
Some definitions conflict with the Win 10/11 SDK d3dcommon.h:
Ok, I just put a fix in that should resolve that issue. I am now using d3dcommon.h
for the definitions in d3dx9.h
.
Is it normal that the keeper hand is a bit transparent?
That is because when I draw the texture I draw it with blending enabled. This is because the texture is all black and only has the hand and menu on it. If I draw it without blending then it will only show the hand and the menu items and then a black screen.
Technically it should not be transparent. The game is trying to write directly to the render target. However, since writing to a render target is slow and not yet supported in dxwrapper I have it write to a black texture and then do blending to show it on the screen. Later I will find a better way to do this.
After working around #65 Dungeon Keeper 2 is always crashing at the end of the loading screen. It creates a series of weirdly sized DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY surfaces which get turned into IDirect3DTexture9 textures. I guess the Lock2 is somehow wrong.
With only ConvertToDirectDraw7/ConvertToDirect3D7 it works:
Dd7to9:
full logs
https://gist.github.com/Trass3r/6854537d31416ff1b8b68e365db44306 https://gist.github.com/Trass3r/da4f799bfcd6a10253f6fae310f43df1