forked from ValveSoftware/Proton
-
-
Notifications
You must be signed in to change notification settings - Fork 272
/
Copy pathdai_xinput.patch
141 lines (128 loc) · 5.13 KB
/
dai_xinput.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
From 4fd6c1a286dd2babd098decf045522be1dff5656 Mon Sep 17 00:00:00 2001
From: Cameron Moore <moore.cameron1111@gmail.com>
Date: Sat, 3 Feb 2024 21:21:50 -0500
Subject: [PATCH] user32: [GAMEFIX] Fix xinput support for Dragon Age
Inquisition
user32: [GAMEFIX] 1/2 Dragon Age Inquisition: fix xinput support
https://bugs.winehq.org/show_bug.cgi?id=47070
I'm not completely sure on the specifics of why the bug happens,
but there are two main threads involved. Thread A owns the window
object for the game. Thread B makes all the calls to XInputGetState.
However, Thread B checks if the window has focus to receive keyboard
inputs every frame. Thread B calls AttachThreadInput to attach its
message queue to the Thread A's window a few times before the bug
starts occurring along with one separate time at the start where
Thread A attaches Thread B's message queue to the window as well.
The message queue is detached one last time and then Thread B no
longer has access to the window.
My workaround checks GetFocus for when it starts receiving Null
for a response (meaning it does not have access to a window anymore).
Prior to this, AttachThreadInput stores the IDs of the two threads
which call the function the very first time (hopefully this works
with the EA App as I've been debugging this with Origin which doesn't
seem to call either of the two WINAPI functions as long as you load
straight into the game from the Origin library menu). When GetFocus
realizes it does not have a window for the thread, it calls
AttachThreadInput with the two thread IDs. This allows Thread B to
access the window, which let's GetFocus return the proper window
handle, which then let's the program access XInputGetState meaning
the controller finally works.
Anyway, as far as the final cause of the bug: it might be because
of thread prioritization causing Thread B to AttachThreadInput to
be called by it last as the only time Thread A calls it, it does
not detach the message queue afterwards. This leads me to believe
that the bug might just be caused by incomplete wine
functionality / stubs. Although, this part is speculation.
user32: [GAMEFIX] 2/2 Dragon Age Inquisition: fix xinput support
Wrap hack with a SteamGameId check and cache it.
---
dlls/user32/input.c | 22 +++++++++++++++++++++-
dlls/win32u/input.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index f91b65a5f56..dda952262ac 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -814,8 +814,28 @@ HWND WINAPI GetActiveWindow(void)
HWND WINAPI GetFocus(void)
{
GUITHREADINFO info;
+ HWND retValueWindow;
+ static HWND prev = 0;
+ const char *sgi;
+ static int is_DragonAgeInquis = -1;
+
info.cbSize = sizeof(info);
- return NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ) ? info.hwndFocus : 0;
+
+ retValueWindow = NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ) ? info.hwndFocus : 0;
+
+ if (is_DragonAgeInquis)
+ {
+ if ((is_DragonAgeInquis == 1) ||
+ (is_DragonAgeInquis = ((sgi = getenv("SteamGameId")) && !strcmp(sgi, "1222690"))))
+ {
+ if (retValueWindow == 0 && prev != 0)
+ NtUserAttachThreadInput(0, 0, 1);
+ else
+ prev = retValueWindow;
+ }
+ }
+
+ return retValueWindow;
}
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
index 6268c978dab..1dbb6690c03 100644
--- a/dlls/win32u/input.c
+++ b/dlls/win32u/input.c
@@ -30,6 +30,8 @@
#pragma makedep unix
#endif
+#include <sys/prctl.h>
+#include <string.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "win32u_private.h"
@@ -596,6 +598,41 @@ HWND get_focus(void)
BOOL WINAPI NtUserAttachThreadInput( DWORD from, DWORD to, BOOL attach )
{
BOOL ret;
+ static int visited = 0;
+ static DWORD fromThreadForHack = 0;
+ static DWORD toThreadForHack = 0;
+ static char processNameForHack[16];
+ static const char* DAIprocessName = "DragonAgeInquis";
+ static const char* DAIGameLoopName = "GameLoop";
+ static int is_DragonAgeInquis = -1;
+ const char *sgi;
+
+ if (is_DragonAgeInquis)
+ {
+ if ((is_DragonAgeInquis == 1) ||
+ (is_DragonAgeInquis = ((sgi = getenv("SteamGameId")) && !strcmp(sgi, "1222690"))))
+ {
+ prctl(PR_GET_NAME, processNameForHack);
+ TRACE("Process Name: %s\n", processNameForHack);
+ if (strncmp(DAIprocessName, processNameForHack, 15) == 0 || strncmp(DAIGameLoopName, processNameForHack, 8) == 0)
+ {
+ if (!visited)
+ {
+ TRACE("First Visit Process Name: %s\n", processNameForHack);
+ fromThreadForHack = from;
+ toThreadForHack = to;
+ visited = 1;
+ }
+
+ if (from == 0 && to == 0 && visited)
+ {
+ TRACE("00 Process Name: %s\n", processNameForHack);
+ from = fromThreadForHack;
+ to = toThreadForHack;
+ }
+ }
+ }
+ }
SERVER_START_REQ( attach_thread_input )
{
--
2.48.1