DirectDraw seems to assume the DDSD_CAPS flag is always set in CreateSurface.
This flag even has a comment in ddraw.h mentioning it's "default".
Some games set ddsCaps members without explicitly setting the DDSD_CAPS flag,
which causes DDrawCompat to incorrectly detect some capabilities. These checks
now always assume the ddsCaps member is valid even if DDSD_CAPS is not set.
Fixes a crash when launching Rogue Spear, mentioned in issue #2.
Legacy DirectDraw interfaces specify the z-buffer format as a single bit depth
number instead of as a DDPIXELFORMAT struct. DirectDraw seems to convert a
legacy z-buffer bit depth of N into a DDPIXELFORMAT with dwFlags = DDPF_ZBUFFER,
dwZBufferBitDepth = N and dwZBitMask set to 1s in the lowest N bits.
Some drivers (so far noticed with AMD only) report the list of supported
z-buffer bit depths incorrectly, resulting in a game potentially selecting a
bit depth that can't actually be created via the legacy interfaces.
For example, the driver may report 16 and 32 bits as supported whereas all
32 bit z-buffer pixel formats use only 24 bits for z-buffer (with the
remaining bits unused or used as stencil buffer). Meanwhile the same driver
doesn't report 24 bits as supported when it's actually supported.
This fix overrides the set of supported z-buffer bit depths in D3DDEVICEDESC
structs for HAL devices to align with the actually supported pixel formats.
Fixes a startup issue in Rainbow Six mentioned in issue #2.
When a surface is created without an explicit capability to specify the type
of surface to create, it only accepts a pixel format that matches the current
display mode. Since the display mode is forced to 32 bit color depth under
DDrawCompat, creating such surfaces could either fail if a different pixel
format is specified (even though it could match the emulated color depth),
or it could be created with the wrong color depth if no pixel format is given.
To prevent these issues, the DDSCAPS_OFFSCREENPLAIN capability is added to all
"untyped" surfaces, which accepts any color depth and already has code in place
to match the emulated display mode's color depth when no pixel format is given.
Fixes#1
Fixes an issue with Fallout's window disappearing from the taskbar every other
time it's minimized.
Also fixes StarCraft's Save Screen Capture dialog being hidden after the main
window is restored.
Commandos 2 reacts to WM_DISPLAYCHANGE messages by reapplying the full-screen
cooperative level and the display mode. This makes the RestoreDisplayMode call
(which itself generates WM_DISPLAYCHANGE) ineffective.
Additionally, on WM_ACTIVATE it removes the primary surface, which DDrawCompat
was relying on for full-screen detection.
This fix returns DDERR_EXCLUSIVEMODEALREADYSET if the app tries to set
full-screen cooperative level while inactive. The tracking of full-screen
mode is now done via a dummy surface instead of the primary surface.
Some DirectDraw methods are implemented by delegating to the same method
in a higher interface version. In this case, the hooking logic could be
executed twice, leading to unwanted side effects. This is now avoided.
Aiming to fix Alt-Tabbing issues (such as black screen instead of desktop)
by temporarily setting the cooperative level to windowed mode, restoring
the display mode and minimizing the main window when the app is inactive.
It's not sufficient to make g_renderingRefCount atomic, because after it is
found to be nonzero in beginGdiRendering, a call to endGdiRendering from
another thread may make it zero before beginGdiRendering has a chance of
entering the critical section. This would mean that the DirectDraw primary
surface is no longer locked, even though beginGdiRendering expects that it is.
To prevent potential issues, the g_renderingRefCount check is now also
guarded by the critical section.
GetWindowDC(GetDC(NULL)) may return a special window with a class name of
"CompatWindowDesktopReplacement". Presumably the shim engine installs an
IAT hook for GetWindowDC that replaces this window handle with the normal
desktop window handle.
CALL_ORIG_FUNC(WindowFromDC) returns with an unpatched pointer, therefore
it doesn't perform the above replacement. This results in using the
replacement window's clipping region (whole screen) instead of the desktop
window's clipping region (empty), and things become visible that shouldn't
be, e.g. some character symbols at the top left corner of the screen when
launchning Diablo II.
As a workaround, WindowFromDC is used without CALL_ORIG_FUNC.