Closed automatedbugreportingfacility closed 2 weeks ago
I noticed that when I open the config overlay in Wild Wild West: The Steel Assassin, the game cursor will drift to the lower right corner.
Is it drifting constantly, or only occasionally while moving the mouse? If it's the latter, I can reproduce it, though it's in a random direction during active mouse movement and pretty rare. Maybe it's easier to reproduce with high polling rate mouse. The game periodically calls SetCursorPos after every flip (no idea what for), and the mouse hook is temporarily uninstalled and reinstalled during that, which might allow for a mouse move event to slip through unblocked.
especially that the game will occasionally crash when the config overlay is dismissed.
This I have never seen. Please enable CrashDump=full, it might produce a usable dump file next time it happens. If it's easy to reproduce, LogLevel=debug could also be useful.
I've made some further tests, and this is related to DPI scaling. Please set the DPI scale factor to 150% or 125% (DpiAwareness=unaware
as well to fix the broken cursor) and retest.
The drift is constant and does not depend on any mouse movement, the game cursor moves even if the overlay cursor is not moved at all. The drift starts immediately after opening the config overlay. My mouse allows switching the polling rates, and it does not seem to affect the drift speed.
Debug log: DDrawCompat-VRDMfc.zip
The main thread stack from the crash dump is:
[0x0] ntdll!NtWaitForAlertByThreadId+0xc 0x19f614 0x77a1fcf9
[0x1] ntdll!RtlpWaitOnAddressWithTimeout+0x64 0x19f618 0x77a1fa4d
[0x2] ntdll!RtlpWaitOnCriticalSection+0x18d 0x19f648 0x77a0023a
[0x3] ntdll!RtlpEnterCriticalSectionContended+0x1aa 0x19f6e8 0x77a00089
[0x4] ntdll!RtlEnterCriticalSection+0x49 0x19f720 0x5fc698f6
[0x5] ddraw_5fc40000!AcquireDDThreadLock+0x16 0x19f72c 0x5fdfe0c0
[0x6] ddraw!DDraw::ScopedThreadLock::{ctor}+0x6 0x19f740 0x21504405
[0x7] ddraw!VtableHookVisitor<IDirectDrawSurface4Vtbl,DDraw::ScopedThreadLock>::hookFunc<28,long,IDirectDrawSurface4 *,unsigned long,unsigned long,IDirectDrawSurface4 *,tagRECT *,unsigned long>+0xa0 0x19f740 0x21504405
[0x8] xvideoio!BltSurface+0xc5 0x19f7e8 0x27005a22
[0x9] svpdrv!VrdDibDraw+0x1bc 0x19f814 0x2902a8f1
[0xa] svprun!VrdRun+0x4f41 0x19f87c 0x2902afdd
[0xb] svprun!VrdRun+0x562d 0x19f8fc 0x2902b5a3
[0xc] svprun!VrdRun+0x5bf3 0x19f928 0x29025287
[0xd] svprun!RunProduction+0x467 0x19f9a0 0x507ffa
[0xe] VRDMfc + 0x7ffa!VRDMfc+0x7ffa 0x19fb40 0x19fbc0
[0xf] 0x19fbc0!+ 0x19fb44 0x50e648
[0x10] VRDMfc + 0xe648!VRDMfc+0xe648 0x19fb48 0x5c747365
[0x11] 0x5c747365!+ 0x19fbc8 0x6e75614c
[0x12] 0x6e75614c!+ 0x19fbcc 0x32336863
[0x13] 0x32336863!+ 0x19fbd0 0x696e692e
[0x14] 0x696e692e!+ 0x19fbd4 0x0
The game periodically calls SetCursorPos after every flip (no idea what for), and the mouse hook is temporarily uninstalled and reinstalled during that, which might allow for a mouse move event to slip through unblocked.
Just a wild guess, but is the case of the overlay being dismissed while the mouse hook is temporarily disabled handled correctly? I noticed that in the case of a crash, the cursor will continue to drift for a while after I dismiss the overlay until a crash occurs. In the lucky case, the cursor will stop moving immediately after closing the overlay.
I've made some further tests, and this is related to DPI scaling. Please set the DPI scale factor to 150% or 125% (DpiAwareness=unaware as well to fix the broken cursor) and retest.
Of course, that was one of my first ideas too, but it wasn't enough. Based on your logs, I assume you have changed the game's Hardware Configuration to "No page flipping". With that, I can reproduce the cursor drift now.
The main thread stack from the crash dump is:
That doesn't look like something that crashed, it's just waiting for the DirectDraw critical section. The crash must have happened on a different thread. Debug logs might indicate which one.
Anyway, even without page flipping and with high DPI scaling, I can't reproduce it. I pressed shift+f12 continuously for a few minutes so that the overlay rapidly turns on and off, but no crashes.
Based on your logs, I assume you have changed the game's Hardware Configuration to "No page flipping". With that, I can reproduce the cursor drift now.
Yes, as mentioned at https://github.com/narzoul/DDrawCompat/issues/306#issuecomment-2126756466, "No page flipping" is the only configuration option that delivers a perfectly smooth 60 FPS animation when DDrawCompat is used (bar a special case or two, but I digress).
The exact steps I use to reproduce the crash: on the main menu screen, press SHIFT+F11 to open the overlay screen. After a random amount of time (1/2/3 seconds), press SHIFT+F11 to dismiss. If the cursor continues to drift even with the overlay closed, it will crash as soon as you move the mouse (this is a detail I missed, moving the mouse is necessary after all). If the drift doesn't continue -> bring up the overlay again to retry. A minor detail I just noticed: when the cursor continues the drift with the overlay closed, instead of moving the mouse, I can bring up the overlay again and avoid the crash. Please remember to use CpuAffinity=all
-- the unstable nature of the crash suggests it might be a race condition.
I've just figured out I can use .ecxr
on the dump file, and it led me to this:
0:010> .ecxr
eax=00000000 ebx=00000200 ecx=00000000 edx=002b3000 esi=000002d0 edi=00000500
eip=5ff764d0 esp=0e5afdac ebp=0e5afdc4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
ddraw!Overlay::Control::isEnabled:
5ff764d0 f7411800000008 test dword ptr [ecx+18h],8000000h ds:002b:00000018=????????
Stack trace:
[0x0] ddraw!Overlay::Control::isEnabled 0xe5afdac 0x5ff7210d
[0x1] ddraw!`anonymous namespace'::lowLevelMouseProc+0xdd 0xe5afdb0 0x75f45ba9
[0x2] user32!DispatchHookA+0x89 0xe5afdcc 0x75fb3473
[0x3] user32!__fnHkINLPMSLLHOOKSTRUCT+0x33 0xe5afe0c 0x77a354ed
[0x4] ntdll!KiUserCallbackDispatcher+0x4d 0xe5afe40 0xe5aff2c
[0x5] 0xe5aff2c!+ 0xe5afe4c 0x5ff5644a
[0x6] ddraw!`anonymous namespace'::messageWindowThreadProc+0x1da 0xe5afec4 0x5ffadbd8
[0x7] ddraw!thread_start<unsigned int (__stdcall*)(void *),1>+0x58 0xe5aff40 0x76e0fcc9
[0x8] kernel32!BaseThreadInitThunk+0x19 0xe5aff78 0x77a280ce
[0x9] ntdll!__RtlUserThreadStart+0x2f 0xe5aff88 0x77a2809e
[0xa] ntdll!_RtlUserThreadStart+0x1b 0xe5affe4 0x0
Looks like g_capture
is dead when if (!g_capture->isEnabled())
is executed in lowLevelMouseProc()
.
EDIT: the mouse hook is installed asynchronously:
void resetMouseHook()
{
Gdi::GuiThread::executeAsyncFunc(resetMouseHookFunc);
}
So there's no guarantee that g_capture
isn't cleared between the time resetMouseHookFunc()
is scheduled and the moment it's actually executed. This may lead to lowLevelMouseProc()
running with a null g_capture
.
Thanks, both issues should be fixed in v0.5.4 now. The cursor will still drift when moving the mouse while the config overlay is open, which seems to be a side effect of the frequent GetCursorPos/SetCursorPos calls, combined with the general cursor position inaccuracy of DPI unaware mode. The cursor is not supposed to be able to move at all when LowLevelMouseProc returns 1, but apparently this isn't quite working correctly in this case. I can't do much about it, but it also doesn't seem to cause any other serious problems.
I noticed that when I open the config overlay in Wild Wild West: The Steel Assassin, the game cursor will drift to the lower right corner. This reminded me of a comment I read at https://github.com/narzoul/DDrawCompat/issues/338#issuecomment-2211725395 :
I'm not sure if this behavior is a result of some event not being caught/redirected properly or rather the game acting weird in the absence of some expected input event, but I thought I'd report it anyway, especially that the game will occasionally crash when the config overlay is dismissed.