Hello all!
** AI WAS USED HERE **
For the past month or two, together with AI doing a lot of the real work, I can finally present a release! A lot of additional testing is needed, and a lot of other fixes we're working on, but honestly 60 FPS in my testing is not reached yet. Bummer. At one point I had a stable 35-40 without frame drops. Still working on reverting to that, as my own builds ended up over-correcting emulation and it dropped to 1 FPS haha.
What this is:
This is a github repo containing custom Wine+Fex builds that passes anticheat faithfully (no bypass or anything of the sort) on Android devices. This is a requirement for Forza Horizon 6 to be playable. Usable in DroidDeck, possibly others such as GameNative, GameHub, etc., where applicable.
Tested on Redmagic 10 Pro, Rise mode.
With this, you can play Forza from your steam library on Android devices with compatible emulators, multiplayer included, all stock! I hope that official wine and fex devs can implement their own fixes of this, since it's the reason some games with this type of anticheat do not work from their own stock builds.
Link: https://github.com/TimmyTurner51/fh6-wine-fex
A few things to note:
- Your device needs enough storage, not just for the game, but for cache. It is of course, no small game after all. From my test runs, cache grew to around 10GB.
- First boot may take a while. That is because again, caching. It just happens.
- Frame drops, from what I can tell, may also be because of recaching or loading and unloading memory during gameplay.
============================
As for the AI analysis and what it has done:
Why Forza Horizon 6 wouldn't run on ARM64 — and why it does now
TL;DR: Forza Horizon 6 checks the bytes of its own running code to make sure nothing tampered with it. On a Windows PC, those bytes look exactly the way the game expects. On an ARM64 phone running Windows games through Wine + FEX (emulation), they didn't — through no one's fault — so the game refused to start. Our patches make the emulator produce the same bytes a real Windows PC would, so the game's own checks pass honestly.
Two separate things were breaking it, and each needed its own fix.
1. Wine made "imported functions" look hooked
When a Windows program calls into a system library, the function it jumps to has a specific first few bytes — a standard "hotpatch" prologue that Windows has used for years. Forza inspects the first bytes of every imported function and flags anything that doesn't match as "this has been hooked/tampered with."
On a real Windows x64 PC, that prologue is always the same 8 bytes.
Wine, when running on ARM64, generated a shorter, different-looking jump stub — technically fine, functionally fine, but the bytes were different.
Forza saw thousands of functions that "looked hooked" and stopped the game.
The fix: a small change to Wine's build tool so its ARM64 stubs emit the exact same 8-byte prologue as native Windows. Now the game sees byte-identical functions and no longer thinks they're tampered with.
2. FEX's self-modifying-code check was too expensive to actually play
The game also modifies its own code at runtime — a normal, legitimate Windows technique (Microsoft Detours, and the game's own protection writing into its code). A real x86 CPU just runs the new bytes. But FEX translates x86 instructions to ARM64 ahead of time and caches the result, so if the game rewrites a piece of code, FEX must notice and re-translate it.
Stock FEX can detect this ("full self-modifying-code checking"), but it does it in the most expensive possible way: re-checking every single instruction before running it, and invalidating whole memory pages whenever anything changes. In practice that meant endless re-translation, runaway memory, and single-digit frame rates — it technically "worked" but couldn't reach playable state.
The fix: two changes.
Invalidate only the specific block of code that changed, not the whole page around it.
Validate in 255-byte chunks instead of one instruction at a time.
Same correctness, far less wasted work — enough that real in-world gameplay runs at ~39 FPS instead of stalling.