Proton
Proton copied to clipboard
Forza Horizon 4 (1293830)
Compatibility Report
- Name of the game with compatibility issues: Forza Horizon 4
- Steam AppID of the game: 1293830
System Information
- GPU: Radeon RX6900XT
- Driver/LLVM version: Mesa 21.1.0/12.0.0
- Kernel version: 5.12-rc5
- Link to full system information report as Gist
- Proton version: experimental-6.3-20210401
I confirm:
- [x] that I haven't found an existing compatibility report for this game.
- [x] that I have checked whether there are updates for my system available.
Symptoms
The game crashes at start.
Reproduction
Always.
UPDATE with Proton experimental-6.3-20210723b
The following problems still remain unresolved:
-
At startup and when changing graphics settings, the game shows a black screen. To show the picture from the game, you need to press <Alt + Tab> twice to switch to a any other window and return back to the game. The bug is repeated with both RADV and AMDVLK. Demonstration: https://youtu.be/GSOvB-LeUkA
-
~~During first race in Fortune Island event the game crashes every time. Demonstration: https://youtu.be/k73nyalMLPs Proton log: https://drive.google.com/file/d/1bRO5nTtGyM6TEhxyFOjTbIoxcT8DLHMq/view?usp=sharing (105.1 MB)~~ UPD: Fortune Island event is playable with Proton experimental-6.3-20211004
-
Unable to add a friend to the session. The game says that there are no friends online. Game Bar is also not called by <Super + G>.
-
When trying to find a club, the game shows the error "There is no Windows program configured to open this type of file."
After clicking on the "Ok" button, the screen goes out, and to return the picture you need apply workaround solution from issue 1, after which we see another error "There was an error communicating the Forza Horizon 4 server. Please try again later."
-
PROTON_LOG = 1 is too verbosive, which makes it impossible to use it. If it's just stupid to go in and exit the game without playing for a second, then 500Mb of logs will be written to the disk. And for an hour of the game, 100Gb of logs are accumulated. The logs are flooded with messages
trace: seh: dump_unwind_info
with assembler opcodes. And FPS with PROTON_LOG = 1 sags at least three times. steam-1293830.zip -
Vibration of triggers does not work on Microsoft gamepads imitating traction, thus killing the wow effect that I got playing for the first time in Forza Horizon 4 on Xbox One X.
This is what the game needs and is missing from Wine
api-ms-win-core-kernel32-legacy-l1-1-2.dll:
VerifyVersionInfoA
api-ms-win-gaming-tcui-l1-1-0.dll:
ShowProfileCardUI
ShowPlayerPickerUI
ProcessPendingGameUI
Jup, same here, thought it would work after MS Flight Sim did but apparently there's something that need's more work.
I've written two patches:
https://source.winehq.org/patches/data/201351
gamingtcui patch
diff --git a/configure.ac b/configure.ac
index 5b7f09de924..f584cecf733 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2979,6 +2979,7 @@ WINE_CONFIG_MAKEFILE(dlls/api-ms-win-eventing-controller-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/api-ms-win-eventing-legacy-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/api-ms-win-eventing-provider-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/api-ms-win-eventlog-legacy-l1-1-0)
+WINE_CONFIG_MAKEFILE(dlls/api-ms-win-gaming-tcui-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/api-ms-win-gdi-dpiinfo-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/api-ms-win-mm-joystick-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/api-ms-win-mm-misc-l1-1-1)
@@ -3320,6 +3321,7 @@ WINE_CONFIG_MAKEFILE(dlls/fusion/tests)
WINE_CONFIG_MAKEFILE(dlls/fwpuclnt)
WINE_CONFIG_MAKEFILE(dlls/gameux)
WINE_CONFIG_MAKEFILE(dlls/gameux/tests)
+WINE_CONFIG_MAKEFILE(dlls/gamingtcui)
WINE_CONFIG_MAKEFILE(dlls/gdi.exe16,enable_win16)
WINE_CONFIG_MAKEFILE(dlls/gdi32)
WINE_CONFIG_MAKEFILE(dlls/gdi32/tests)
diff --git a/dlls/api-ms-win-gaming-tcui-l1-1-0/Makefile.in b/dlls/api-ms-win-gaming-tcui-l1-1-0/Makefile.in
new file mode 100644
index 00000000000..5007bd06de2
--- /dev/null
+++ b/dlls/api-ms-win-gaming-tcui-l1-1-0/Makefile.in
@@ -0,0 +1 @@
+MODULE = api-ms-win-gaming-tcui-l1-1-0.dll
\ No newline at end of file
diff --git a/dlls/api-ms-win-gaming-tcui-l1-1-0/api-ms-win-gaming-tcui-l1-1-0.spec b/dlls/api-ms-win-gaming-tcui-l1-1-0/api-ms-win-gaming-tcui-l1-1-0.spec
new file mode 100644
index 00000000000..d7fa8a12e75
--- /dev/null
+++ b/dlls/api-ms-win-gaming-tcui-l1-1-0/api-ms-win-gaming-tcui-l1-1-0.spec
@@ -0,0 +1,7 @@
+@ stdcall ProcessPendingGameUI(long) gamingtcui.ProcessPendingGameUI
+@ stub ShowChangeFriendRelationshipUI
+@ stub ShowGameInviteUI
+@ stdcall ShowPlayerPickerUI(ptr ptr long ptr long long long ptr ptr) gamingtcui.ShowPlayerPickerUI
+@ stdcall ShowProfileCardUI(ptr ptr ptr) gamingtcui.ShowProfileCardUI
+@ stub ShowTitleAchievementsUI
+@ stub TryCancelPendingGameUI
diff --git a/dlls/gamingtcui/Makefile.in b/dlls/gamingtcui/Makefile.in
new file mode 100644
index 00000000000..0a88c98c539
--- /dev/null
+++ b/dlls/gamingtcui/Makefile.in
@@ -0,0 +1,4 @@
+MODULE = gamingtcui.dll
+
+C_SRCS = \
+ gamingtcui_main.c
diff --git a/dlls/gamingtcui/gamingtcui.spec b/dlls/gamingtcui/gamingtcui.spec
new file mode 100644
index 00000000000..998bf4edafd
--- /dev/null
+++ b/dlls/gamingtcui/gamingtcui.spec
@@ -0,0 +1,29 @@
+@ stub DllCanUnloadNow
+@ stub DllGetActivationFactory
+@ stub DllGetClassObject
+@ stub CheckGamingPrivilegeSilently
+@ stub CheckGamingPrivilegeSilentlyForUser
+@ stub CheckGamingPrivilegeWithUI
+@ stub CheckGamingPrivilegeWithUIForUser
+@ stdcall ProcessPendingGameUI(long)
+@ stub ShowChangeFriendRelationshipUI
+@ stub ShowChangeFriendRelationshipUIForUser
+@ stub ShowCustomizeUserProfileUI
+@ stub ShowCustomizeUserProfileUIForUser
+@ stub ShowFindFriendsUI
+@ stub ShowFindFriendsUIForUser
+@ stub ShowGameInfoUI
+@ stub ShowGameInfoUIForUser
+@ stub ShowGameInviteUI
+@ stub ShowGameInviteUIForUser
+@ stub ShowGameInviteUIWithContext
+@ stub ShowGameInviteUIWithContextForUser
+@ stdcall ShowPlayerPickerUI(ptr ptr long ptr long long long ptr ptr)
+@ stub ShowPlayerPickerUIForUser
+@ stdcall ShowProfileCardUI(ptr ptr ptr)
+@ stub ShowProfileCardUIForUser
+@ stub ShowTitleAchievementsUI
+@ stub ShowTitleAchievementsUIForUser
+@ stub ShowUserSettingsUI
+@ stub ShowUserSettingsUIForUser
+@ stub TryCancelPendingGameUI
diff --git a/dlls/gamingtcui/gamingtcui_main.c b/dlls/gamingtcui/gamingtcui_main.c
new file mode 100644
index 00000000000..792a4e64b50
--- /dev/null
+++ b/dlls/gamingtcui/gamingtcui_main.c
@@ -0,0 +1,73 @@
+#include "config.h"
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "hstring.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(gamingtcui);
+
+BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
+{
+ TRACE("(%p, %d, %p)\n", hInstDll, fdwReason, lpvReserved);
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hInstDll);
+ break;
+ }
+
+ return TRUE;
+}
+
+typedef void (*GameUICompletionRoutine)(HRESULT returnCode, void *context);
+HRESULT ShowProfileCardUI(HSTRING targetUserXuid, GameUICompletionRoutine completionRoutine, void *context)
+{
+ FIXME("%p %p %p: stub\n", targetUserXuid, completionRoutine, context);
+
+ if (completionRoutine) {
+ completionRoutine(S_OK, context);
+ }
+
+ return S_OK;
+}
+
+typedef void (*PlayerPickerUICompletionRoutine)(HRESULT returnCode, void *context, const HSTRING *selectedXuids, size_t selectedXuidsCount);
+HRESULT ShowPlayerPickerUI(
+ HSTRING promptDisplayText,
+ const HSTRING *xuids,
+ size_t xuidsCount,
+ const HSTRING *preSelectedXuids,
+ size_t preSelectedXuidsCount,
+ size_t minSelectionCount,
+ size_t maxSelectionCount,
+ PlayerPickerUICompletionRoutine completionRoutine,
+ void *context
+)
+{
+ HSTRING* selectedXuids = (HSTRING*) xuids;
+ size_t selectedXuidsCount = xuidsCount;
+
+ FIXME("%p %p %lu %p %lu %lu %lu %p %p: stub\n", promptDisplayText, xuids, xuidsCount, preSelectedXuids, preSelectedXuidsCount, minSelectionCount, maxSelectionCount, completionRoutine, context);
+
+ /* Assuming xuids == all xbox live user ids for the machine, and preSelectedXuids == the default one, perhaps this will work? */
+ if (preSelectedXuidsCount) {
+ selectedXuids = (HSTRING*) preSelectedXuids;
+ selectedXuidsCount = preSelectedXuidsCount;
+ }
+
+ if (completionRoutine) {
+ completionRoutine(S_OK, context, selectedXuids, selectedXuidsCount);
+ }
+
+ return S_OK;
+}
+
+HRESULT ProcessPendingGameUI(BOOL waitForCompletion)
+{
+ FIXME("%d: stub\n", waitForCompletion);
+ return S_OK;
+}
I haven't yet tested the game. The gamingtcui patch is preliminary, based solely on the (mostly lacking) MSDN documentation. In other words, I don't expect this to work. But perhaps it'll shed some light on where to go next, or save those interested in debugging this from the boilerplate trouble.
Thank you for the patches. I've tried them and now the game crashes with Unimplemented function errors: KERNEL32.dll.GetSystemCpuSetInformation and KERNEL32.dll.SetThreadSelectedCpuSets
Hmm, from what I found, it seems that these functions are probably mostly used by UWP apps. Interesting, I thought that Forza Horizon 4 from Steam is no longer based on UWP.
Here are some bad stubs (I haven't written a patch, @jas0n098 did the test):
BOOL WINAPI GetSystemCpuSetInformation(void* information, ULONG buffer_length, PULONG returned_length, HANDLE process, ULONG flags)
{
if (!returned_length) return FALSE;
if (!information) {
*returned_length = 50; /* good enough? */
} else {
*returned_length = buffer_length;
memset(information, 0, buffer_length);
}
return TRUE;
}
void WINAPI SetThreadSelectedCpuSets(HANDLE thread, ULONG* cpu_set_ids, ULONG cpu_set_id_count)
{
}
Specfile entries should be something like:
@ stdcall GetSystemCpuSetInformation(ptr long ptr ptr long)
@ stdcall SetThreadSelectedCpuSets(ptr ptr long)
~~It appears to be crashing after though, for seemingly unrelated reasons:~~ Edit: nevermind, this is not the right crash!
11038.547:0144:0148:Ret KERNEL32.K32GetModuleBaseNameA() retval=00000009 ret=143016517
11038.547:0144:0148:Call ucrtbase._stricmp(0022ebf0 "ntdll.dll",0022ec50 "ntdll.dll") ret=143016528
11038.547:0144:0148:Ret ucrtbase._stricmp() retval=00000000 ret=143016528
11038.547:0144:0148:trace:seh:dispatch_exception code=c0000005 flags=0 addr=0000000000000000 ip=0000000000000000 tid=0148
11038.547:0144:0148:trace:seh:dispatch_exception info[0]=0000000000000008
11038.547:0144:0148:trace:seh:dispatch_exception info[1]=0000000000000000
~~This is called from a TLS callback (144BAC930) in ForzaHorizon4.exe , and it appears to iterate over loaded modules, trying to find ntdll.dll (~60,000 lines of K32GetModuleBaseNameA
), where it subsequently crashes on trying to run a null address. Apparently this game has pretty heavy anti-hooking/cheating code, so this might be an intentional crash?~~
Alright, the actual crash seems to be here:
11064.402:0144:015c:trace:module:load_dll Loaded module L"\\??\\C:\\windows\\system32\\rsaenh.dll" at 000000006FC40000
...
11064.405:0144:015c:trace:module:process_attach (L"rsaenh.dll",0000000000000000) - START
11064.405:0144:015c:Call LDR notification callback (proc=0000000143010560,reason=1,data=000000000BC9CD90,context=0000000000000000)
...
11064.832:0144:015c:Ret KERNEL32.K32GetModuleBaseNameA() retval=0000000e ret=143010888
11064.832:0144:015c:Call ucrtbase._stricmp(0bc9c2b8 "kernelbase.dll",0bc9c8a0 "kernelbase.dll") ret=14301089c
11064.832:0144:015c:Ret ucrtbase._stricmp() retval=00000000 ret=14301089c
11064.832:0144:015c:trace:seh:dispatch_exception code=c0000005 flags=0 addr=0000000000000000 ip=0000000000000000 tid=015c
...
11064.832:0144:015c:trace:seh:dump_unwind_info unwind info at 0000000146EB1B20 flags 2 prolog 0x3d bytes function 0000000143010560-000000014301206F
(I'm keeping the earlier crash because of the similarity to this crash)
This seems to me like some kind of anti-hooking code:
11037.569:0144:0148:Call ntdll.LdrRegisterDllNotification(00000000,143010560,00000000,0022ede8) ret=1430123bc
Right after this crash, it'll run:
11064.832:0144:015c:Call ucrtbase._wfopen(7f0aebc40580 L"C:\\users\\...\\Local Settings\\Application Data\\ForzaHorizon4\\scratch\\CrashReport.xml",1450430a8 L"w") ret=14335d1bd
A quick look at the file doesn't appear to show much useful information (at least nothing that isn't already present in the log)
I think this is as far as I can figure out, I'll leave this to the geniuses at wine :)
(Big thanks to @jas0n098 for trying patches and sending the logs)
Apparently this gets it to boot:
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index a7e6d712df1..4e2dc538862 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -1581,6 +1581,8 @@ NTSTATUS WINAPI LdrRegisterDllNotification(ULONG flags, PLDR_DLL_NOTIFICATION_FU
TRACE( "(%x, %p, %p, %p)\n", flags, callback, context, cookie );
+ return STATUS_SUCCESS;
+
if (!callback || !cookie)
return STATUS_INVALID_PARAMETER;
Looks good enough to upstream? :stuck_out_tongue_winking_eye:
So it's almost certainly some kind of anti-hooking code then.
Trying to patch out more (e.g. if the callback is 0x62166B50
in TpAllocWork
, set it to a fake callback instead) does advance further, but I don't think this is going to work properly. There are numerous checks littered through the game, including within work threads that also handle game code.
I think all the issues preventing the game start are clear now, while it might take a bit of time for cleaning up the patches and debugging what goes after the game start . @qsniyg since you've done some debugging and might be curious what it wants at this point I can share our findings if you contact me on IRC or e-mail privately.
Any new progress? :-)
Vkd3d-proton work is needed to go further, and is ongoing. Please be patient :wink:
How can i use these patches ? Can somebody please explain
How can i use these patches ? Can somebody please explain
@edd-dev It doesn't work yet, so there's no point really...
My forza is giving error when trying to open this Dll is missing:
can anybody help me?
My forza is giving error when trying to open this Dll is missing:
can anybody help me?
what dlls are missing? You haven't given any.
My forza is giving error when trying to open this Dll is missing: can anybody help me?
what dlls are missing? You haven't given any.
007c:err:hid:parse_descriptor Unknown (bTag: 0x0, bType: 0x0) 00c8:err:module:import_dll Library api-ms-win-gaming-tcui-l1-1-0.dll (which is needed by L"Z:\ForzaHorizon4.exe") not found 00c8:err:module:import_dll Library api-ms-win-core-memory-l1-1-3.dll (which is needed by L"Z:\ForzaHorizon4.exe") not found 00c8:err:module:import_dll Library api-ms-win-core-kernel32-legacy-l1-1-2.dll (which is needed by L"Z:\ForzaHorizon4.exe") not found 00c8:err:module:LdrInitializeThunk Importing dlls for L"Z:\ForzaHorizon4.exe" failed, status c0000135
Sorry dll: api-ms-win-gaming-tcui-l1-1-0.dll
This is what the game needs and is missing from Wine
api-ms-win-core-kernel32-legacy-l1-1-2.dll: VerifyVersionInfoA api-ms-win-gaming-tcui-l1-1-0.dll: ShowProfileCardUI ShowPlayerPickerUI ProcessPendingGameUI
noob question here maybe, but how did you find out the wine dlls that are required for this app to function?
Those aren't the only issues to fix for the game to run though.
This is what the game needs and is missing from Wine
api-ms-win-core-kernel32-legacy-l1-1-2.dll: VerifyVersionInfoA api-ms-win-gaming-tcui-l1-1-0.dll: ShowProfileCardUI ShowPlayerPickerUI ProcessPendingGameUI
noob question here maybe, but how did you find out the wine dlls that are required for this app to function?
@netizener Looking at the log after attempting to run the game...
@Tk-Glitch Those aren't the only issues to fix for the game to run though.
What (do we know of so far) needs to be implemented for FH4 to run?
Sorry dll: api-ms-win-gaming-tcui-l1-1-0.dll
same :< where i can DL that DLL?
Sorry dll: api-ms-win-gaming-tcui-l1-1-0.dll
same :< where i can DL that DLL?
@paulopogi01 afaik it needs to be implemented in Wine...
@CCF100 It's not only functions to implement. The game has special needs on both wine and vkd3d-proton fronts, and they are being addressed. The last bit can be found here if you're curious: https://github.com/HansKristian-Work/vkd3d-proton/pull/621
Forza Horizon 4 should now be playable with latest Proton Experimental on AMD GPU with mesa-git. :-)
What's the problem with NVIDIA?
So this game doesn't run with NVIDIA?
Forza Horizon 4 should now be playable with latest Proton Experimental on AMD GPU with mesa-git. :-)
As far as I understand this is a UWP game, is there a chance that with the new version proton and other uwp games will start?
Game does start with latest Proton Experimental, but crashes during the first race. BTW its NVIDIA GPU
Same here, Game works perfectly fine just driving around running on Nvidia GPU, but also crashes on the first race. Also doesn't launch again, after the crash, it throws a page fault exception:
Unhandled exception: page fault on write access to 0x00000000 in 64-bit code (0x00000001432fe38c).
Also noticed, while at it, controller doesnt seem to work in the welcome menu, but works fine afterwards.
Forza Horizon 4 should now be playable with latest Proton Experimental on AMD GPU with mesa-git. :-)
@rejedai As far as I understand this is a UWP game, is there a chance that with the new version proton and other uwp games will start?
Forza Horizon 4 is a special case, while it is a UWP game, it was (mostly) ported to Win32 so that it could be released on steam. It still uses some UWP functions, however. (This is all based off of my understanding, so things could be wrong, lol)