dgVoodoo 2.82.5: DirectX emulation related stuffs

Table of contents


1. Important notes

First of all: NEVER COPY DDRAW.DLL, D3D8.DLL and D3D9.DLL INTO SYSTEM FOLDERS!! ALWAYS USE A LOCAL INSTALLATION FOR A GAME!
DirectDraw, D3D8 and D3D9 are still existing and widely used system components in Windows. :)

For clarifying, let's see what dlls MS and dgVoodoo use for DirectDraw and Direct3D:

  • MS:

    ddraw.dll- Contains all DirectDraw implementations up to version 7
    d3dim.dll- Contains all Direct3D implementations up to version 6
    d3dim700.dll- Contains Direct3D 7 implementation
    d3d8.dll- Contains Direct3D 8.1 implementation
    d3d9.dll- Contains Direct3D 9Ex implementation

  • dgVoodoo:

    ddraw.dll- Contains all DirectDraw implementations up to version 7
    d3dimm.dll- Contains all Direct3D implementations up to version 7
    d3d8.dll- Contains Direct3D 8.1 implementation
    d3d9.dll- Contains Direct3D 9.0c implementation

So, dgVoodoo packs all of its pre-D3D8 implementation into one module, d3dimm.dll, which differs in name from the MS one (note the extra 'm' in the name).
Thus, copying it to the system folder by accident won't cause any harm. In spite of that, it is not recommended.


2. General overview

If you want to wrap an old DirectX stuff then just copy dgVoodoo's dlls to the application folder and launch that. DirectX rendering is configurable similarly to Glide. (See DirectX related CPL options) DirectDraw is usable without Direct3D but there are no 3D rendering capabilities exposed to the applications in that case.
Direct3D8/9 are standalone components, no need for DirectDraw to use them. In spite of that it is a good idea to copy DDraw.dll along with D3D8.dll (and maybe D3D9.dll) because a lot of movie playback system (e.g. DirectShow) rely on DDraw even in D3D8 games. dgVoodoo DDraw and D3D8/9 has the ability and internal support to cooperate if the situation requires.

All the interfaces of old DirectX (that is, all DirectDraw interfaces and Direct3D 3/5/6/7/8/9 interfaces) are almost fully supported, and existing implementation is improved version by version by more and more reverse engineering and finetuning.

Since DirectX is not a pure hardware-only rendering API, basically two types of virtual video cards can be used, like back in the old days, hehe. Four extra video card types are added to utilize different chipset features and provide correct vendorID/hardwareID. Available video card types:

  • One that simulates an old SVGA with hw-capabilites only for 2D blitting operations.
    With such a card, only a software 3D rendering device can be used.
  • One (imaginary) video card that has its custom hw 3D rendering support.
    This card provides support for full hardware acceleration including 'Transform & Light'.
  • GeForce4 Ti 4800
  • ATI Radeon 8500
  • Matrox Parhelia-512
  • GeForce FX 5700 Ultra
  • Geforce 9800 GT

For more detailed capabilities, see the technical info.

Software rendering devices does not use real software rendering in dgVoodoo. I think that a software rasterizer has no reason for existence nowadays and didn't want to write one just for fun so they use hw accelerated rendering in the background. The point is, towards the applications they logically appear as software devices.

DirectX renderer needs less GPU power (for general cases) than Glide renderer and has its own internal shader code generator for generating specialized shaders.

DX emulation has a method for fast CPU-access of locked surfaces. The current method is not the final version and going to be improved later. The reason of not using that one all the time but it is up to the user's choice is that this method is not 100% safe and can cause crashes under certain circumstances. It depends on the wrapped application.

Important to note that compatibility with MS DirectDraw is not completely guaranteed, especially with very old applications written in the win95/Win98 era. Those applications might utilize DirectDraw/GDI interaction which is not fully supported in dgVoodoo. I would like to improve that somehow, in later versions.


3. Some technical info

I say 'almost fully supported' when talking about DX support because there are some functions on certain interfaces of which functionality is somewhat unclear or totally unimportant, so they either not implemented at all or just partially because I did not have time and patience to figure out their exact behavior. Think about a total of 5-6 functions of all the DX interfaces, I hardly believe that anything used them.

For D3D8.1 and D3D9, the following features are not implemented but planned to be in the future:

  • RT-Patches (maybe some day)
  • Full D3D9Ex functionality

Internal virtual 3D card has the following 3D hardware capabilities:

  • Supports transforming and all kind of lighting with flat, Gouraud and Phong shading, max 8 active lights
  • Supports 6 clipping planes
  • Supports vertex bending with 3+1 weights
  • Supports matrix palette of 256 elements for indexed vertex blending
  • Supports texture coordinate generating & transformation, projective texturing
  • Supports all contemporary pixel formats for textures and render targets with four different RGBA order (altough the order is not yet exposed in the CPL app)
  • Supports compressed textures (DXTC1-5)
  • Supports volume textures with limited number of texture formats
  • Supports Z-buffer (of course) and stenciling (but there is no W-buffer)
  • Supports vertex and pixel fog
  • Supports colorkeying with one texture (with colorkey blending or colorkey discarding)
  • Supports all texture sampling modes
  • Paletted textures
  • Depth textures
  • 16 vertex streams
  • Vertex tweening
  • Supports point sprites
  • Full SM1/2/3 and DX9-level fixed function pipeline support
  • 256, 512 or 1024 vertex shader constants (configurable)
  • Supports adaptive N-Patches (ATI TruForm)

The other 4 card types are not an exact emulation of the given chipsets with some real ATI/nVidia/Matrox driver version. They are just present to bias the available rendering capabilities and properties toward a real ATI, nVidia or Matrox card:

GeForce4 Ti 4800 capabilities:

  • Same as the internal virtual 3D card, except:
  • No 32 bit z-buffer support
  • No support for adaptive N-Patches (ATI TruForm)
  • Full cut colorkeying
  • No indexed vertex blending
  • Maximum supported pixel shader version is ps1.3
  • Max 96 vertex shader constants

ATI Radeon 8500 capabilities:

  • Same as the internal virtual 3D card, except:
  • No 32 bit z-buffer support
  • Plain colorkeying
  • Max 57 matrices for indexed vertex blending
  • No paletted texture support
  • 8 vertex streams
  • Max 192 vertex shader constants

Matrox Parhelia-512 capabilities:

  • Same as the internal virtual 3D card, except:
  • No 32 bit z-buffer support
  • No support for adaptive N-Patches (ATI TruForm)
  • Plain colorkeying
  • No paletted texture support
  • Maximum supported pixel shader version is ps1.3

GeForce FX 5700 Ultra capabilities:

  • Same as the internal virtual 3D card, except:
  • Only shader model 2.x support
  • No 32 bit z-buffer support
  • No support for adaptive N-Patches (ATI TruForm)
  • Full cut colorkeying

GeForce 9800 GT capabilities:

  • Same as the internal virtual 3D card, except:
  • No 32 bit z-buffer support
  • No support for adaptive N-Patches (ATI TruForm)
  • Full cut colorkeying
  • No paletted texture support through D3D8/9
  • No indexed vertex blending support

Since I cannot enumerate all the capabilities here, check them out with DXCapsViewer if interested.
Also, those capabilities might be changed in the future if I get more accurate information about the hardwares in question.

DirectDraw and Direct3D objects supports all types of rendering devices that are supported in original DirectX.
Direct3D8/9 support HAL and software device types.

In MS pre-Direct3D8 implementations Direct3D7 is the only one that can be used with hardware vertex transformation and lighting, through a Transform & Light (T&L) device (but I guess it casually falls back to software vertex processing if the device driver does not support the complete vertex operation pipeline that is currently set).

In all other cases software vertex processing is used. In dgVoodoo vertex processing is always routed to the hardware when possible.
However, it's not so simple: software vertex processing is unavoidable in Direct3D in some cases, for example when an application wants Direct3D to do only vertex processing without rendering or to calculate visibility, or, when the rendering extent must be updated when drawing primitives through a non-T&L device (this is not too important in practice but I included it because of full compatibility). Also, vertex processing for Direct3D3 can only be done in software because of the execution logic of execute buffers.
It all means that dgVoodoo has a software T&L vertex processing engine like MS Direct3D for such cases, duplicating the hw functionality. However for transforming, bending, lighting, fogging and texture coordinate transforming calculations dgVoodoo uses fast vectorized SSE2 code instead of scalar FPU. (It should be noted that in newer DX version like DX7 MS uses SSE2 too.)

For software execution of D3D8/9 vertex shaders, dgVoodoo has a CPU code generator, as does MS. This is currently x86/x64 only and the ARM64 version runs the shaders slower but it is planned to be changed.

What is more, for software emulation of vertex shader code in DX8/9, MS seems to apply an internal compiler, that compiles from shader code to x86 bytecode. Wow, what a nice feature!! I should do the same, but probably it all is not too relevant on modern CPUs.)

Phong shading (per-pixel shading) is not supported by MS Direct3D, only Gouraud (per-vertex). However the internal virtual 3D card can externally be forced to Phong shading through the CPL app but keep in mind that it can cause heavy GPU usage because Direct3D lighting is quite complex, typical hardware implementations supports 8 active lights with a lot of properties and components. Also, Phong shading is only applicable when the application commits all its transforming and lighting calculations to the D3D runtime. Unfortunately it is very common that games do their own T&L calcs and use D3D as a lowlevel rasterizer for the rest. It is especially true when a game is written for multiple platforms or multiple 3D APIs like Glide, D3D, OpenGL, etc. Direct3D3 always uses software vertex processing so Phong shading cannot be applied there at all.

DX8 is a horse of another colour from the beginning of a new era. Applications written for that usually heavily utilize multiple vertex streams through real vertex and index buffers along with built-in hw T&L pipeline and/or shaders without any calculations done in software. I think I shouldn't detail DX9. It's a way too new API compared to the previos ones. :)

Phong shading is only applicable with full fixed function vertex/pixel pipeline usage. If an application is rendering through a vertex and/or pixel shader in DX8/9 then Phong cannot be utilized.


4. Application resolutions and refresh rates

An application using DirectX can only detect available resolutions and associated refresh rates by asking DirectDraw/DX8/DX9 to enumerate them. There are two slight problems with it in practice:

  • Modern hardware does not necessarily report some low resolutions like 320x200, 640x480, etc.
  • Old hardware was not able to report refresh rates or query the current one in general, back then when 60/75Hz CRTs were the standard displays. Thus, most of the games/applications just used 0 for refresh rate when setting the resolution which means 'unspecified or default' refresh rate.

To workaround the first case, dgVoodoo keeps a list of 'classic' resolutions. These are the following:

  • 320 x 200 (X-mode is also supported in DDraw)
  • 320 x 240, (X-mode is also supported in DDraw)
  • 640 x 400,
  • 640 x 480,
  • 800 x 600,
  • 1024 x 768,
  • 1280 x 1024

If a resolution of that list is not amongst the ones that your modern adapter reports then dgVoodoo forces enumerating it to the application.

Handling refresh rates:

If General\EnumerateRefreshRate is enabled

Value of the forced refresh rate is determined in the following order:

  • The forced refresh rate (part of the forced resolution) if it's defined
  • The refresh rate of the desktop display mode in GeneralExt\DesktopResolution if it's defined
  • The current desktop refresh rate

All of the resolutions are enumerated with the forced refresh value to the application. When initializing D3D or setting display mode through DDraw then any incoming required refresh rate value is accepted but replaced with the forced one.

For defining a custom refresh rate in the resolution selector combo box (DirectX tab), see chapter 'Resolution and refresh rate overriding' in the general readme.

If General\EnumerateRefreshRate is disabled

Value of the default refresh rate is determined in the following order:

  • The refresh rate of the desktop display mode in GeneralExt\DesktopResolution if it's defined
  • The current desktop refresh rate

dgVoodoo keeps a list of 'classic' refresh rates (CRT) of 60, 70, 72, 75, 80, 85 Hz. If a resolution in the internal list is available with a refresh rate of a 'classic rate' - 1 Hz then the 'classic rate' variant is also forced into the list. This is to avoid problems, coming from converting modern rational refresh rate values to single integers with truncating/rounding, for these classic general refresh rates.

For initializing D3D or setting a display mode through DDraw:
If the incoming required refresh rate is 0 then the default value is used.
If the incoming required refresh rate is not 0 then it must match one of the available refresh rates for the given resolution in the internal list. Request fails with an error otherwise.


In either case, if the final refresh rate is unsupported by your monitor at a given resolution then the closest supported one will be selected.


5. About fullscreen and windowed mode

Choosing fullscreen or windowed working mode is part of the DirectDraw API. Some games or demoscene stuffs run only in fullscreen so one could think what cool it would be to have them running in windowed mode. I thought the same so wanted to enable by default the same method to switch between them as used for Glide. There are some problems however: the ways handling fullscreen and windowed mode via DirectDraw are totally different in the aspect of the driving code. So, forcing an application into an unexpected situation may cause glitches or crashes. Also, a game may have its on mechanism for mode switching with which dgVoodoo could conflict. Due to those theoretic things, and because I experinced some problems with some games, I decided to emulate the original DirectDraw behavior by default: when a fullscreen application loses the focus then its window gets minimized and when it regains that its window is restored and enters fullscreen again and no manual switch is available. Also, there are no changes applied on the app window like style and overridden messages, etc.

If you make sure that a given game does not conflict with dgVoodoo's Alt-Enter thing then you can enable that in the CPL app. Also, you can force it to windowed mode if 'app controlled fullscreen/windowed' option is disabled at the game startup (and choose windowed mode in the general settings), without Alt-Enter. Forcing a windowed application to fullscreen can only be done by manual switch because there is no way to 1) detect when an application begins its rendering and 2) switch to fullscreen.

(But, think about it, windowed to fullscreen does not make any sense. The resolution used comes from the window size but the window may get resized or repositioned when switching mode, so..., it's confusing.)

What is more, since DirectDraw was a one-monitor-API in practice, integrating windowed applications in a multimonitor environment is already a problem even for MS, I think. If such an app is even forced to fullscreen mode then it may crash or misworks for reasons I do not want to word here.

Lost mode is emulated in default DX emulation mode, namely when switching between windowed/fullscreen mode by Alt-Enter is disabled. This is because some DX applications count on losing their surfaces when their window loses focus and their code paths can be mislead if they remain 'unlost'. (This is a result of bad programming technique as DX SDKs clearly state that an application shouldn't rely on window focus lost or any other circumstances.)

On the other hand, there are incomplete or buggy DX applications that can't restore when they get reactivated and just get stuck. So, introducing lostmode emulation is up to a potential feature loss, as such applications likely worked well with older dgVoodoo versions. In order to keep this feature dgVoodoo applies auto-restore for the needed elements when such a situation is detected.


6. DirectX options

  • Disable and passthru to real DirectX

    As it says, if you want to disable DirectX without removing dgVoodoo's DLLs then use this option.

  • Videocard

    You can select between the internal virtual 2D (SVGA) and 3D accelerated cards.

  • VRAM

    Onboard videomemory of the selected videocard.

  • Filtering

    Various texture filtering modes can be forced here, starting from simple point sampled to high level anisotropic. Keep in mind however that forcing other than the application default can result in rendering glitches, or it can completely break some visual effects!

  • KeepFilterIfPointSampled

    If enabled then the forced texture filter type is only applied if the filter type set by the application is not point-sampled. Forcing point-sampled textures usually leads to various artifacts (coming from colorkeying, alpha transparency or misaligned texture coordinates) so the best is to leave them unfiltered. This can be useful for game 3D scene backgrounds and HUDs that are generally drawn as non-filtered textures.

  • No mipmapping

    Disabling mipmappig (forcing largest mip texture level).

  • Resolution

    Here you can override the application resolution and refresh rate. See detailed explanation of static/dynamic resolutions in the general Readme.

  • Antialiasing

    For 3D rendered surfaces you can force MSAA. Option 'Application controlled' is meaningful only for DX8. For DDraw/DX it is equivalent to 'Off'.

  • Application controlled fullscreen/windowed state

    Since choosing this state is part of DirectDraw, you must disable this option to control that via general settings.

  • Disable Alt-Enter to toggle screen state

    To prevent conflicting with an application built-in Alt-Enter handler.

  • Bilinear DD/CPU operations

    2D bitmap copying can involve stretching in DirectDraw. However the applied stretching filter cannot be controlled via the API and early hw used simple point sampling. It can result pixelated appearance here and there but you can force bilinear filtering which looks cooler for most cases. But, it can also introduce various artifacts especially when colorkeying is also applied during blitting.
    This option also controls how CPU-written surface data is scaled when resolution is forced.
    Try forcing bilinear texture filtering for achieving similar effects for D3D8 games.

  • Apply Phong shading when possible

    See technical info.

  • Force vSync

    Forcing vertical retrace.

  • Fast video memory access

    Provides an alternative method for accessing video memory of DX surfaces by the CPU. Try this one if an application renders at a low frame rate.

  • dgVoodoo Watermark

    Similarly to 3Dfx watermark in Glide, you can use dgVoodoo's own one to see if something is driven through dgVoodoo's DirectX.


7. DirectX additional options

  • AdapterIDType

    You can define what type of driver version and vendor id's the wrapper should report to the application; Some games rely on that information so it can be useful for them. It can be defined only for SVGA and Internal3D card types; the others have their own wired information. It can be undefined (default), nVidia, AMD or Intel.

  • VendorID, DeviceID, SubsystemID, RevisionID

    It can be defined only for SVGA and Internal3D card types. You can overwrite these properties even if a non-default AdapterIDType is defined. Say, you defined an nVidia ID type but would like to refine the vendor ID.

  • ExtraEnumeratedResolutions

    You can define up to 16 custom resolutions that are enumerated to the application.
    It's useful for apps that support all or a very special resolution and you want to select that through the app itself rather than force it through the wrapper externally (avoiding rendering glitches). You can also use keywords max, max_4_3 and max_16_9 here along with refresh rates to define maximum resolutions calculated from the desktop resolution with the appropiate aspect ratio. 'Max' defines no aspect ratio so it is practically equivalent to your current desktop resolution.

  • DefaultEnumeratedResolutions

    What resolutions are to be enumerated to the application by default:

    • All: All of the resolutions supported by your GPU and the classic ones. (default)
    • Classics: Only the classic resolutions.
    • None: No any resolution are enumerated to the application. You must define at least one extra custom resolution in this case or the application won't see any which is a problem.

  • EnumeratedResolutionBitdepths

    You can define what bit depths for display modes are to be enumerated and supported by dgVoodoo. Any subset of {8, 16, 32} or simply All. (default)

  • Dithering

    • Disabled: Dithering is always disabled, ending up 16-bit quality rendering on 16 bit surfaces.
    • Appdriven: The application can enable and disable dithering. When enabled, the selected dithering effect is applied.
    • ForceOn16Bit: Dithering is always enabled for 16 bit targets and the selected dithering effect is applied.
    • ForceAlways: Dithering is always enabled and the selected dithering effect is applied (default).

  • DitheringEffect

    • Ordered2x2: Ordered dithering with a 2x2 dithering matrix
    • Ordered4x4: Ordered dithering with a 4x4 dithering matrix
    • Pure32Bit: 32 bit rendering quality (default)

  • DitherOrderedMatrixSizeScale - integer scale value for dither matrix size

    • 1 = normal, 2 = double size, etc.
    • 0 = automatic (the aim is to have some retro feel\&look) (default)

  • DepthBuffersBitDepth

    • Appdriven: Internal bit depth of depth buffers is the same as the application defines. (default)
    • ForceMin24Bit: Internal bit depth of depth buffers is minimum 24 bit.
    • Force32Bit: Internal bit depth of depth buffers is always 32 bit. This one is not recommended.

  • Default3DRenderFormat

    Default 3D rendering format for 'upscaled' bit depths, including legacy ARGB8888 32 bit format. It has no effect on CPU- and blit- only accessed rendering. If the rendering format has higher precision than the output color space format then it is downscaled when the image is presented to the output.

    • Auto: The format is automatically chosen and aligned with the current output color space. (default)
    • ARGB8888: 32 bit with 8 bits for each component.
    • ARGB2101010: 32 bit with 10 bits for color components. This can give higher dynamic range on a HDR display but can also break the rendering because of the less number of bits for alpha. Try and use it only experimentally.
    • ARGB16161616: 64 bit with 16 bits for each component.

  • MaxVSConstRegisters

    Max number of vertex shader constant registers (DX8/9 only). It can only be defined for SVGA and Internal3D card types. Valid values are 256 (default), 512 or 1024. The larger value the larger performance loss.

  • NPatchTesselationLevel

    You can disable tesselation or force a tesselation level for the 3D rendering. This is a very dumb option and not recommended for general usage. N-Patch tesselation has more parameters than just tesselation level, like cubic/linear position, quadratic/linear normals and other adaptive parameters. You can only force the level here which also disables adaptive mode. Also, forcing only affects the fixed function and vs.1.x vertex pipeline. Altough tesselation works with all shader versions, forced tesselation is only enabled at D3D8-level because of performance- and historical reasons. This option is intended for experimental purposes, like, you want to see how a given mesh in a game would like at a given tesselation level. Don't forget, for curved triangles the mesh data has to contain normal vectors. If omitted, triangles are still tesselated but remain flat.

  • MSD3DDeviceNames

    Some application checks against the Microsoft names of D3D devices (bad practice). If none of found then they probably won't work at all. dgVoodoo's device names differ from the Microsoft ones but enabling this option forces the wrapper to report MS device names.

  • RTTexturesForceScaleAndMSAA

    By default, size of 3D-renderable (rendertarget) textures are internally scaled along with the forced resolution, and also, they inherits the forced MSAA chosen for the rendering. Rendertarget textures are typically used for pre-rendering reflections, shadows, water and such, but their unexpected size and MSAA type can introduce some unwanted glitches. If that is the case then you can try disabling this option to have them at their original intended state but this can easily drive dgVoodoo into unresolvable situations producing errors. The debug layer reports if such a situation is detected and this option is not applicable for the given application.

  • SmoothedDepthSampling

    D3D8 only: by default, depth textures gets some additional filtering when sampling them. Depth textures are typically used for rendering shadows so they are smoothed by default. Disabling this option leads to simple sampling as it is done in real D3D8, getting more jagged shadows.

  • DeferredScreenModeSwitch

    If true the switching to full screen is deferred after the application initialized the DirectX device; can be useful for games that don't expect rendering window changes during initialization and crash

  • PrimarySurfaceBatchedUpdate

    If enabled then direct changes of the primary surface are batched up to present them one time. If disabled then each change is immediately presented (debug-like mode). It affects only DirectDraw.

  • SuppressAMDBlacklist

    Certain AMD GPU's are detected (Vega architecture as of now) and forced to use a working but unoptimal code path in D3D11 to fix the solid-color-texture issue. If this option is enabled then you can suppress the code path to check it out if a new driver release itself fixes the bug.

  • DisplayOutputEnableMask

    This option is for the case when you have multiple display outputs and want fine grained control for them by enabling/disabling them one by one. It can be useful for D3D9 multihead- or very special applications where you want to enable only individual displays on your monitor wall.
    It is recommended to change this option from the CPL app.

    Each bit in this 32 bit value corresponds to a display output. Display outputs of the adapters are numbered sequentially. If Adapter0 has n display outputs and Adapter1 has m display outputs attached then the lowest n bits match Adapter0 display outputs, the next m bits match Adapter1 outputs, and so on. The lowest bit in a group corresponds to Output0. If a bit value is 0 then the display output is disabled for the device enumeration, in other words, it is invisible to the application.


8. Tips and known issues

  • Always try to run an application with 'application controlled fs/windowed state' and disabled 'Alt-Enter' for the first time. If 'Alt-Enter' is enabled then the wrapper makes some changes to the application window which can cause some applications to miswork or even crash.

  • Also, always try an application without enabling 'Fast video memory access' for the first time as that method may be unsafe for the application in question, and, unortunately can cause inappropriate working.

  • Upscaling (forcing resolution) for old 8 bit paletted DDraw applications are not recommended. Paletted things and forced resolution don't work well together, but I want to fix it in the future.
    Upscaling scenes by forcing resolution, where no 3D-rendered objects are presents, has no sense anyway.

  • Forcing vertical retrace is not always a good idea. There are games of which loaders refreshes the screen at maximum speed (without vertical sync) while loading textures, meshes, etc. If vSync is forced to on then it can take ages while it all gets over.


9. Why doesn't dgVoodoo DX emulation start up?

I got reports about cases with dgVoodoo DirectX emulation not starting up. The story is simple, one copies the DX dll files into the given application folder, next to the executable, makes sure that DX emulation is enabled on the CPL, and in spite of that, when starting the application dgVoodoo isn't utilized at all, dgVoodoo watermark doesn't show up in the corner if the app starts at all. Thanks to the Guys on Vogons, who are helping me a lot, they come out with 2 reasons:

  • Some of the DX dlls (ddraw.dll, d3d8.dll) are registered in the KnownDLLs section of the Windows registry. When they are then the operating system always loads the system versions of those dlls. Removing the entries from
    "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs"
    is undangerous and can be safely done with Regedit. This issue causes the majority of the problems.

  • A bit marginal but existing problem with DirectDraw is that it can be initialized through Windows' OLE mechanism which identifies objects with GUIDs. The 'GUID-dll name' pairs are also stored in Windows registry but Microsoft switched to absolute dll paths in Windows 8(?) instead of the relative ones present in Windows 7, so the OLE-accessed DirectDraw is always the system one in that case. The registry entries in question can be changed back to relative paths, but since Regedit requires TrustedInstaller privilege level for that, and you have to search for the entries yourself, it is a complicated process, I don't recommend you to experiment with it. Luckily most of the old programs access DirectDraw directly, bypassing OLE.

I know that these details are technical like hell, and I don't at all expect an average user to tinker the operating system registry by hand.

To solve the problem, apply Narzoul's registry file, this is the most simple way:

https://raw.githubusercontent.com/narzoul/DDrawCompat/master/Tools/InstallDDrawCOMRedirection.reg