FunkyFr3sh / cnc-ddraw

GDI, OpenGL and Direct3D 9 re-implementation of the DirectDraw API for classic 2D games for better compatibility with Windows ME, 2000, XP, Vista, 7, 8, 10, 11, Wine (Linux/macOS/Android) and Virtual Machines
https://discord.gg/afWXJNDDF5
MIT License
2.34k stars 148 forks source link

support newer interfaces #21

Closed Trass3r closed 4 years ago

Trass3r commented 4 years ago

like IDirectDraw4

FunkyFr3sh commented 4 years ago

Can you name me an example game?

Note: Any game that's using direct3d in one way or another is not supported

Trass3r commented 4 years ago

I see. Tested on Dungeon Keeper 2.

FunkyFr3sh commented 4 years ago

Yeah, I don't think that one is going to work.

Maybe try out DDrawCompat or DxWnd, they're both using the original system ddraw/d3dx dlls and might work (cnc-ddraw is standalone solution and doesn't use them...)

https://github.com/narzoul/DDrawCompat https://sourceforge.net/projects/dxwnd/files/

Trass3r commented 4 years ago

I know these. I was interested in testing cnc-ddraw's shader support.

FunkyFr3sh commented 4 years ago

May have a look into adding support for newer ddraw versions, but for now I'm closing this issue since I'm not aware of any game currently that could in theory work

elishacloud commented 4 years ago

@FunkyFr3sh, if you are interested I can give you a list of older games (like Heroes of Might and Magic 4) that use the v4 or v7 DirectDraw interfaces and do not use the Direct3D interfaces.

Trass3r commented 4 years ago

They also have a software renderer in DK2 so it could work in theory.

FunkyFr3sh commented 4 years ago

@elishacloud Sure, I'll have a look into them.

@Trass3r Oh I see, should be able to see what function is missing with a log file. I attached a debug build below that will create a file named cnc-ddraw.log ddraw.zip

Trass3r commented 4 years ago

v4 doesn't add much. I think I ran into GetDeviceIdentifier.

/*** Added in the V4 Interface ***/
STDMETHOD(GetSurfaceFromDC) (THIS_ HDC, LPDIRECTDRAWSURFACE4 *);
STDMETHOD(RestoreAllSurfaces)(THIS);
STDMETHOD(TestCooperativeLevel)(THIS);
STDMETHOD(GetDeviceIdentifier)(THIS_ LPDDDEVICEIDENTIFIER, DWORD);
FunkyFr3sh commented 4 years ago

Not looking good for DK2... It was indeed calling GetDeviceIdentifier but even with that one added it would still try to query a IDirect3D interface and then it's crashing. Return value isn't checked so I can't do anything, a DDERR_UNSUPPORTED doesn't work.

image

Trass3r commented 4 years ago

For switching the engine there's HKCU\Software\Bullfrog Productions Ltd\Dungeon Keeper II\Configuration\Video\Engine Id. 2 means D3D. 1,3,4 means Software 2D, 3D, 3D MMX respectively.

But it looks like the enumeration does not respect this and always calls D3D.EnumDevices(). What happens if you just delegate to the original QueryInterface for D3D guids?

elishacloud commented 4 years ago

@elishacloud Sure, I'll have a look into them.

Below is a list of games I know about. All of these will run with DirectDraw APIs. There are a couple of these that require one or two Direct3D interface APIs, specifically these ones: EnumDevices and FindDevice.

Here is the list of games broken down by interface usage. Just keep in mind that I put the highest interface used by the game. For example, I put Atlantis 3: The New World under DirectDraw7, but it actually uses all 4 interfaces.

DirectDraw1:

DirectDraw2:

DirectDraw4:

DirectDraw7:

elishacloud commented 4 years ago

BTW: I tested Dungeon Keeper 2 and it requires the Direct3D interfaces. It won't work with just DirectDraw interfaces, even with the software renderer.

Trass3r commented 4 years ago

Do you know which methods? It definitely uses the EnumDevices method but shouldn't use anything else. Not sure if the GoG patch influences the renderer choice.

FunkyFr3sh commented 4 years ago

I nop'ed some of the code just to try it and it kinda worked. It would then just release the IDirectDraw4 interface. Then it will query a IDirectDraw which it is actually using. Then it would query a IDirect3D2 interface but I could just return DDERR_UNSUPPORTED and it was fine. Then it would query a IDirectDraw2 interface just to call GetAvailableVidMem and release it... Finally it would actually do it's thing on the IDirectDraw interface...

It's crashing after the cutscene, not sure if I want to spend more time with it :P

image

Trass3r commented 4 years ago

Yeah it does some crazy things like calling EnumDevices in different places and also creates temporary windows and stuff like that. I guess because the video code was a separate EA library. I always use the -nomovies parameter to avoid problems and all the resolution switching. With -level mpd1 you also directly get into a level.

not sure if I want to spend more time with it :P

Feel free to put your changes in a test branch.

FunkyFr3sh commented 4 years ago

It works now somewhat with the latest commit...

Had to set Engine Id to 4, all others didn't work + maxgameticks=60 + noactivateapp=true in ddraw.ini + the following hack:

static BOOL once; if (!once) once = g_ddraw->ref-- + 1;

Inserted here: https://github.com/CnCNet/cnc-ddraw/blob/8c0cb61394df0f1eecb24278ec023fd0c0a2aab5/src/dd.c#L735

I saw a DDSD_ZBUFFERBITDEPTH in the logs, so that's probably what's breaking it now

FunkyFr3sh commented 4 years ago

Looks like it's actually working fine now. I'll leave a build here in case someone wants to try it:

cnc-ddraw_Dungeon-Keeper2.zip

Must set in registry:

HKCU\Software\Bullfrog Productions Ltd\Dungeon Keeper II\Configuration\Video\Engine Id = 4

Edit: Latest release (1.3.9.0) works now without the need to change any registry keys https://github.com/CnCNet/cnc-ddraw/releases

Trass3r commented 4 years ago

Nice work. Weird that it gets detected as a trojan.

FunkyFr3sh commented 4 years ago

I have the cloud detection disabled because it's causing way too many false positives so I didn't notice it

I just reported it to MS

FunkyFr3sh commented 4 years ago

Fixed

image