https://bugs.winehq.org/show_bug.cgi?id=57394 Zhiyi Zhang <zzhang(a)codeweavers.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution|--- |WONTFIX --- Comment #12 from Zhiyi Zhang <zzhang(a)codeweavers.com> --- This is just a buggy game. It crashes because of a STATUS_ACCESS_VIOLATION at 0x140106b2b. First, to launch the game without the launcher, use `wine game.bin EasyFun width=3840 height=2160 version=0 no_loginsdk=1 app_name=AstralTaleUpgrade` Then put a breakpoint in dispatch_exception() when STATUS_ACCESS_VIOLATION is encountered. You will see the game crash site is at 0x140106b2b under winedbg. ``` 140106b23 31 d2 XOR EDX,EDX 140106b25 45 31 c0 XOR R8D,R8D 140106b28 45 31 c9 XOR R9D,R9D 140106b2b ff d0 CALL RAX <- RAX is supposed to be a function pointer, the function prototype should have four parameters. ``` The RAX value is from a function at 0x1401067e0 ``` undefined8 * FUN_1401067e0(undefined8 *param_1,longlong param_2) { ... DAT_14138fc90 = *(code **)(lVar9 + 0x2f0); ---> lVar9 is pointer to d3d9_device_vtbl, so DAT_14138fc90 is &d3d9_device_SetVertexShaderConstantF DAT_14138fc98 = *(code **)(lVar9 + 0x300); DAT_14138fca0 = *(code **)(lVar9 + 0x310); DAT_14138fca8 = DAT_14138fc90; ---> DAT_14138fca8 gets the same value from DAT_14138fc90, which is &d3d9_device_SetVertexShaderConstantF DAT_14138fcb0 = DAT_14138fc98; DAT_14138fcb8 = DAT_14138fca0; if ((DAT_14138fcf1 != '\0') && (uVar11 < 4)) { bVar12 = DAT_14138fcf0 == '\0'; ---> DAT_14138fcf0 is 1 if the d3d9 device is from Direct3DCreate9Ex() instead of Direct3DCreate9 puVar5 = (undefined8 *)(lVar9 + 0x4f0); ---> This is where it starts to go bad. Remember that lVar9 is a pointer to d3d9_device_vtbl But d3d9_device_vtbl[0x4f0] is outside of the range of d3d9_device_vtbl. So it just points to some data at &d3d9_device_vtbl[0x4f0]. With Wine's built-in d3d9 at Wine-9.0, d3d9_device_vtbl[0x4f0] points to a string in the .rdata section. Obviously, executing a read-only string will trigger an access violation. if (bVar12) { puVar5 = (undefined8 *)(lVar9 + 0x478); } DAT_14138fca8 = (code *)*puVar5; puVar5 = (undefined8 *)(lVar9 + 0x480); if (!bVar12) { puVar5 = (undefined8 *)(lVar9 + 0x4f8); } DAT_14138fcb0 = (code *)*puVar5; puVar5 = (undefined8 *)(lVar9 + 0x488); if (!bVar12) { puVar5 = (undefined8 *)(lVar9 + 0x500); } DAT_14138fcb8 = (code *)*puVar5; (*DAT_14138fca8)(DAT_14138fc38,0,0,0); ---> This is at 0x140106b2b, where the access violation happens. (*DAT_14138fcb0)(DAT_14138fc38,0,0,0); (*DAT_14138fcb8)(DAT_14138fc38,0,0,0); } DAT_14138fcc0 = *(undefined8 *)(lVar9 + 0x368); DAT_14138fcc8 = *(undefined8 *)(lVar9 + 0x378); DAT_14138fcd0 = *(undefined8 *)(lVar9 + 0x388); DAT_14138fcd8 = *(undefined8 *)(lVar9 + 0x368); DAT_14138fce0 = *(undefined8 *)(lVar9 + 0x378); DAT_14138fce8 = *(undefined8 *)(lVar9 + 0x388); return param_1; } ``` So let's test if it's possible that d3d9_device_vtbl[0x4f0] can contain any valid code. ``` static void test_device_4f0(void) { HRESULT (WINAPI *p_d3d9_device_SetVertexShaderConstantF)(IDirect3DDevice9Ex *iface, UINT reg_idx, const float *data, UINT count); IDirect3D9 *d3d9 = (void *) 0xdeadbeef; IDirect3D9Ex *d3d9ex; HRESULT hr; ULONG ref; void **vtable; hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex); ok(hr == D3D_OK, "Got hr %#lx.\n", hr); hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9); ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef, "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9); ref = getref((IUnknown *) d3d9ex); ok(ref == 2, "Unexpected refcount %lu.\n", ref); ref = getref((IUnknown *) d3d9); ok(ref == 2, "Unexpected refcount %lu.\n", ref); ok(d3d9 == (void *)d3d9ex, "Expected the same pointer.\n"); vtable = (void *)d3d9ex->lpVtbl; ok(vtable[0] == d3d9ex->lpVtbl->QueryInterface, "Got unexpected vtable.\n"); p_d3d9_device_SetVertexShaderConstantF = (void *)(vtable[0x4f0]); hr = p_d3d9_device_SetVertexShaderConstantF(d3d9ex, 0, 0, 0); ok(hr == S_OK, "Got hr %#lx.\n", hr); IDirect3D9_Release(d3d9); IDirect3D9Ex_Release(d3d9ex); } ``` The result on Windows is that an exception occurred. So the answer is NO. So is the same for vtable[0x478] ``` PS Y:\> .\d3d9_test.exe d3d9ex d3d9ex.c:5224: this is the last test seen before the exception 0638:d3d9ex: unhandled exception c0000005 at 00007FFB5A88F7AD ``` So, I think this is an application bug. It worked on a previous Wine version most likely because the memory layout made d3d9_device_vtbl[0x4f0] point to some executable code. So an access violation might not happen. This is the case with DXVK 2.4.1 and Wine(a)git a6bf181dafd compiled with default compilation flags. It calls into some function in DXVK and ends up triggering a different exception but the exception is eventually handled. After b21813fa1, we added a new syscall so the memory layout changes a bit and d3d9_device_vtbl[0x4f0] doesn't point to executable code anymore, leading to a crash. The crash also happens on older versions of Wine such as wine-9.0 and builtin d3d9 for the same reason. Also, I can't even launch the game on Windows 11. At this point, I don't think there is much we can do unless the game developer fixes their game. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.