https://bugs.winehq.org/show_bug.cgi?id=19153
--- Comment #23 from Andrew D'Addesio andrew@fatbag.net --- I installed Windows 98SE on my spare PC (with a Radeon Xpress 200 chipset) and ran the tool for three versions of DirectX: * The stock DirectX: 6.1a, 4.06.03.0518, 1999-04-23 * DirectX 7.0, 4.07.00.0716, 1999-09-09 * DirectX 8.1, 4.08.01.0881, 2001-10-30
For each version of DirectX, I ran the tool with and without the "EnumReference" and "EnumNullDevice" registry settings.
The results are: * (IDirect3D 1&2 only) "Ramp Emulation" * (All interfaces) "RGB Emulation" * (All interfaces) "Direct3D HAL" (requires driver support) * (IDirect3D 2 only) "MMX Emulation" * (All interfaces) "Reference Rasterizer" (DX 6-8 only and requires "EnumReference" with nonzero value, briefly mentioned in KB249579) * (All interfaces) "Null device" (DX 6-8 only and requires "EnumNullDevice" with nonzero value, mentioned in DX 6&7 SDKs) * (IDirect3D 7 only) "Direct3D T&L HAL" (DX 7+ and requires driver support)
It appears that DirectX 9 and onwards no longer recognize the "EnumReference" and "EnumNullDevice" settings as I wasn't able to get these devices to show up in Windows XP SP3 (32-bit) on the same machine.
So we would like to add support for these games: * Resident Evil * Carmageddon 2 demo * The Sims Online
without breaking these games: * Moto Racer 2 * Aliens versus Predator * GTA 2 * Rollcage * Donald Duck: Goin' Quackers
The current comments in d3d3_EnumDevices present these issues: a. Motoracer 2 depends on the device names being in writable memory. b. AvP / Motoracer 2 (both Direct3D1 games) break if the reference rasterizer is enumerated. c. GTA 2 (presumably Direct3D3) depends on the HEL device being the first enumerated device and the HAL device being the second enumerated device. d. Rollcage (Direct3D2) tells which is the HAL device and which is the HEL device solely by looking at hal_desc and hel_desc. When it receives a device, it knows that it's looking at the correct device description (hal_desc on the HAL device or hel_desc on the HEL device) if and only if the "Power-of-2 textures only" limitation is set. Once it's looking at the correct description, it discards all devices which have the "perspective correction" flag (presumably) set. e. Donald Duck: Goin' Quackers identifies the devices by the names "Direct3D HAL" and (presumably) "Direct3D HEL".
So, I downloaded the Moto Racer 2 Demo: http://download.cnet.com/Moto-Racer-2-updated-demo/3000-2115_4-10025083.html
I verified that the game installs and runs in Wine 1.7.51-git on Linux (Fedora 22).
### Issue a
I have personally verified issue a: If you replace the instances of "device_name" with string literals, the game demo segfaults immediately upon start (eip=00424875). I undid my change and the game resumed working.
### Issue b
I then replaced "if (ddraw->d3dversion != 1)" with "if (1)" in order to enumerate the HEL device and changed all of the TRACE messages to FIXMEs so that they would appear in the terminal. Even with this change, the game still works for me; here is the output:
fixme:ddraw:d3d1_EnumDevices iface 0x133da4, callback 0x424814, context (nil). fixme:ddraw:d3d3_EnumDevices iface 0x133d9c, callback 0x424814, context (nil). fixme:ddraw:d3d3_EnumDevices Enumerating WineD3D D3DDevice interface. fixme:ddraw:d3d3_EnumDevices Enumerating HAL Direct3D device. fixme:ddraw:d3d3_EnumDevices End of enumeration.
Changing "Direct3D HEL" to "RGB Emulation" has no effect; in fact, renaming both devices to "foo"/"bar" has no effect. So, I thought, "maybe it breaks on one of the other HEL IIDs."
Currently, ddraw.c says this:
/* Do I have to enumerate the reference id? Note from old d3d7: * "It seems that enumerating the reference IID on Direct3D 1 games * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1
It turns out that the mentioned comment was created way back in May 2003:
https://www.winehq.org/pipermail/wine-patches/2003-May/006228.html http://cvs.winehq.org/cvsweb/wine/dlls/ddraw/d3ddevice/Attic/mesa.c?rev=1.96...
- if (version > 1) {
/* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
d1 = dref;
d2 = dref;
ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
if (ret_value != D3DENUMRET_OK)
return ret_value;
- }
If the D3D version is not 1, then enumerate IID_IDirect3DRefDevice.
Yet, the present code does this:
/* Do I have to enumerate the reference id? Note from old d3d7: * "It seems that enumerating the reference IID on Direct3D 1 games * (AvP / Motoracer2) breaks them". So do not enumerate this iid in V1 * ... */ if (ddraw->d3dversion != 1) { /* ... */ hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description, device_name, &hal_desc, &hel_desc, context);
If the D3D version is not 1, then enumerate IID_IDirect3DRGBDevice.
So I replaced IID_IDirect3DRGBDevice with IID_IDirect3DRefDevice, but oddly the game still works. Really, I can't get this game to *not* work.
I haven't tested Aliens versus Predator; it may or may not break on IID_IDirect3DRefDevice; but (at least until I test) I have no reason to suspect it would break on IID_IDirect3DRGBDevice.
### Issue c
I don't have GTA 2 but it's possible that it uses Direct3D3, so that the first device is the RGB device and the second device is the HAL device. In that case, issue c is consistent with the Windows behavior.
### Issue d
I installed Rollcage (first unpatched from the CD and, later, the 1.0b patch). This was the most interesting game to test.
The following comment is no longer accurate:
* Other games (Rollcage) tell emulation and hal device apart by certain * flags. Rollcage expects D3DPTEXTURECAPS_POW2 to be set (yeah, it is a * limitation flag), and it refuses all devices that have the perspective * flag set. This way it refuses the emulation device, and HAL devices * never have POW2 unset in d3d7 on windows. */
There is a mistake in the comment: it refuses all devices that have the perspective flag unset* (not set). When I ORed the flag into hal_desc and hel_desc:
hal_desc.dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_PERSPECTIVE; hal_desc.dpcTriCaps.dwTextureCaps |= D3DPTEXTURECAPS_PERSPECTIVE; hel_desc.dpcLineCaps.dwTextureCaps |= D3DPTEXTURECAPS_PERSPECTIVE; hel_desc.dpcTriCaps.dwTextureCaps |= D3DPTEXTURECAPS_PERSPECTIVE;
the game still worked; when I masked it out instead:
hal_desc.dpcLineCaps.dwTextureCaps &= ~D3DPTEXTURECAPS_PERSPECTIVE; hal_desc.dpcTriCaps.dwTextureCaps &= ~D3DPTEXTURECAPS_PERSPECTIVE; hel_desc.dpcLineCaps.dwTextureCaps &= ~D3DPTEXTURECAPS_PERSPECTIVE; hel_desc.dpcTriCaps.dwTextureCaps &= ~D3DPTEXTURECAPS_PERSPECTIVE;
the game stopped working (it immediately exits after the intro movie). In fact, the original patch to fix EnumDevices mentions this:
http://marc.info/?l=wine-patches&m=117870468623214&w=2
The other flag is D3DPTEXTURECAPS_PERSPECTIVE which is not set on rgb emulation(!= refrast). Rollcage uses this flag to tell rgb emulation from hal.
Thus, it refuses all devices which have D3DPTEXTURECAPS_PERSPECTIVE unset.
Additionally, this comment is no longer accurate:
HAL devices never have POW2 unset in d3d7 on windows.
On my Windows 7 install, the HAL device's hal_desc (D3D1-3) or desc (D3D7) always has D3DPTEXTURECAPS_POW2 and D3DPTEXTURECAPS_NONPOW2CONDITIONAL both unset (which means that "unconditional support is provided for 2D textures with dimensions that are not powers of two" according to MSDN's D3DCAPS9 article).
But it looks like that doesn't matter; I masked out these flags in hal_desc and hel_desc and the game still worked. (The game also works if you OR in one of the flags and mask out the other, or OR in both flags.)
Using a debugger, I found that the game does the following in its callback function (0041D280 in the unpatched version, 0041d250 in version 1.0b) for IDirect3D3::EnumDevices:
- Let ptr = hal_desc.
- If ptr->dcmColorModel == 0, then change ptr to hel_desc.
- If ptr->dwDeviceRenderBitDepth does not contain DDBD(selected_bit_depth), return DDENUMRET_OK (request the next device).
- If ptr->dcmColorModel is odd (this corresponds to D3DCOLOR_MONO) and ptr->dpcTriCaps.dwShadeCaps does not contain D3DPSHADECAPS_COLORGOURAUDMONO, return DDENUMRET_OK.
- If ptr->dcmColorModel is even (this corresponds to D3DCOLOR_RGB) and ptr->dpcTriCaps.dwShadeCaps does not contain D3DPSHADECAPS_COLORGOURAUDRGB, return DDENUMRET_OK.
- If ptr->dpcTriCaps.dwTextureCaps does not contain D3DPTEXTURECAPS_PERSPECTIVE, return DDENUMRET_OK.
- If we have made it to this point, this is a good device.
Upon this quick examination there is no reference to the POW2 flags that I can see, and for me the game still works if the flags are masked out, so I believe we can stop adding the POW2 flags in EnumDevices.
### Issue e
I was unable to get a device named "Direct3D HEL" in DirectX 6.1a, 7.0, 8.1, or later versions, thus I believe we should change "Direct3D HEL" to "RGB Emulation".
---
In short, we want: * d3d1: ramp rgb (hal )? (ref )? (null )? * d3d2: ramp rgb (hal )? mmx (ref )? (null )? * d3d3: rgb (hal )? (ref )? (null )? * d3d7: rgb (hal )? (ref )? (null )? (tnlhal )?
with the correct names ("Ramp Emulation", "RGB Emulation", and so on), and we want the non-matching description of each device (hel_desc on the HAL device or hal_desc on the other devices) to be empty (or almost empty for the HAL device's hel_desc).
I have submitted a patchset so that Wine conforms to this behavior: https://www.winehq.org/pipermail/wine-patches/2015-October/142721.html
The patchset fixes Resident Evil 1 and at least knocks off one of the bugs in The Sims Online trial. Carmageddon 2 demo is actually affected by an issue in FindDevice (FindDevice should accept dwSizes 0xac, 0xcc, and 0xfc in D3DDEVICEDESC); this is also fixed in the patchset.