Game details: per-game AVX and AVX2 (MADEIRA_FEX_AVX) - #172
Merged
Merged
Conversation
## Problem FEX's iOS build synthesizes its host features by hand (`FetchHostFeatures`, `FEX_IOS_HOST`) and never sets `SupportsAVX`, and it returns before any config override is read. Games that check CPUID take their SSE paths, which is the right default. Games compiled for AVX processors do not check: **Ghost of Tsushima** died on its first VEX instruction with `STATUS_ILLEGAL_INSTRUCTION` (c000001d) before reaching its menu. ## Change Needs a companion change in **willfaust/FEX** (`FEX-avx-opt-in.md`, patch `FEX.patch`): with `MADEIRA_FEX_AVX=1` in the environment, the iOS `FetchHostFeatures` sets `SupportsAVX` (and `SupportsAES256` when AES is there) for the ARM64EC module; WOW64 stays without AVX, as on every other FEX host. App side (this PR): - `LibraryEntry.avx` (optional, so older library files decode). - **Game details › Compatibility & performance › AVX and AVX2**, off by default; the section footer says when to use it and that emulated AVX is slower. - `applyEnvironment` sets `MADEIRA_FEX_AVX=1` for that game or unsets it, so one game's choice never stays for the next session. - `docs/LIBRARY.md`: one bullet. ## Evidence Fork builds since 2026-09-26 (iPhone 17 Pro Max, iOS 27): - Ghost of Tsushima (D3D12) ran with AVX on through intros, the main menu and into gameplay in every later session; without it the game stops at its first VEX instruction. - GTA V Enhanced: with AVX on, the processor feature set the guest sees carries the AVX bits (`FeatureSet 0xe3f9ffff` in the fork's hardware-description log line); with AVX off the game still passes its own CPU checks and its Chromium helpers log that they take their SSE paths. Titles differ, which is why this is a per-game switch and not a default. ## Notes / risks - Off by default; nothing changes for a game that does not choose it. - Without the FEX change the switch only sets a variable nothing reads. - Binary to rebuild after the FEX PR: `app/Madeira/arm64ec-windows/xtajit64.dll` (`build/fex-arm64ec`). The fork shipped a second copy (`xtajit64-avx.dll`) and switched links per game at first; that is not needed, since the module itself reads the variable at start-up, and is not ported. - No new Swift file; `project.pbxproj` unchanged. --- 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0189oLHghpaYKLk4f786a6bc Signed-off-by: bahacan16 <190844990+bahacan16@users.noreply.github.com>
willfaust
pushed a commit
that referenced
this pull request
Oct 4, 2026
Squashed from #172; needs willfaust/FEX#9. Signed-off-by: bahacan16 <190844990+bahacan16@users.noreply.github.com>
spitefulowl
added a commit
to spitefulowl/Madeira
that referenced
this pull request
Oct 4, 2026
A library game exports its own engine switches before the session starts (LibraryEntry.applyEnvironment): MADEIRA_FASTSYNC and MADEIRA_FASTSYNC_SEM (Fast synchronization, Fast semaphore waits), MADEIRA_CPU_COUNT, DXMT_D9_ANISO_LIMIT, FEX_X87REDUCEDPRECISION (Reduced-precision x87), MADEIRA_DINPUT_PAD (Controller: XInput and DirectInput), MADEIRA_FEX_AVX (AVX and AVX2, willfaust#172) and MADEIRA_FRAMEGEN (Frame generation, willfaust#171). The bridge then exported madeira.cfg's env.* lines with overwrite, so a cfg line for the same key replaced the game's choice: `env.MADEIRA_FASTSYNC = auto` undid a game's "Fast synchronization: off", and `env.MADEIRA_FEX_AVX = 0` would undo its "AVX and AVX2", although its details page says the game's setting applies. The values also stayed in the app's environment after the session, so a later launch in the same app run (MADEIRA_ONE_SESSION_PER_RUN=0) inherited them. Now a cfg line for one of these keys is skipped, and logged as `[madeira-env] ml1184 KEY=<game's> kept (the game's own setting); madeira.cfg's <value> ignored`, when the game set that key for this launch; the keys are unset when the session ends. Which keys the game set is noted once, before the first cfg line is exported: testing getenv() at each line would take a key's earlier cfg line for the game's own setting, so with two lines for one key Wine would run with the first value while Settings (madeira.cfg is last-line-wins) shows the last. A game's own config lines (This game's config, willfaust#167) are exported after this loop and still win over both; docs/LIBRARY.md states the order. MADEIRA_DINPUT_PAD joined the list later (ml1240): the per-game DirectInput choice now beats the cfg key too, the Session menu says that the choice applies from the next launch (the DirectInput device is made at launch), and docs/CONTROLLERS.md names it the picker's second choice (it said third). check-frontend gains the DirectInput export checks, a source check that the per-launch keys are noted before the cfg loop, and one that every key applyEnvironment exports is in the list and unset at the session's end, so a new switch on the game's page cannot be left out; check-dock-gdi-section searches the longer export loop to its end. Tagged ml1184 and ml1240. Built only: the 2026-09-30 and 2026-10-03 builds carried ml1184/ml1240 with the per-line test, but no device log shows a kept line; the snapshot before the loop is syntax-checked with the iOS SDK. check-frontend and check-dock-gdi-section pass. Signed-off-by: spitefulowl <spitefulowll@gmail.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
FEX's iOS build synthesizes its host features by hand (
FetchHostFeatures,FEX_IOS_HOST) and never setsSupportsAVX, and it returns before any config override is read. Games that check CPUID take their SSE paths, which is the right default. Games compiled for AVX processors do not check: Ghost of Tsushima died on its first VEX instruction withSTATUS_ILLEGAL_INSTRUCTION(c000001d) before reaching its menu.Change
Needs a companion change in willfaust/FEX (
FEX-avx-opt-in.md, patchFEX.patch): withMADEIRA_FEX_AVX=1in the environment, the iOSFetchHostFeaturessetsSupportsAVX(andSupportsAES256when AES is there) for the ARM64EC module; WOW64 stays without AVX, as on every other FEX host.App side (this PR):
LibraryEntry.avx(optional, so older library files decode).applyEnvironmentsetsMADEIRA_FEX_AVX=1for that game or unsets it, so one game's choice never stays for the next session.docs/LIBRARY.md: one bullet.Evidence
Fork builds since 2026-09-26 (iPhone 17 Pro Max, iOS 27):
FeatureSet 0xe3f9ffffin the fork's hardware-description log line); with AVX off the game still passes its own CPU checks and its Chromium helpers log that they take their SSE paths. Titles differ, which is why this is a per-game switch and not a default.Notes / risks
app/Madeira/arm64ec-windows/xtajit64.dll(build/fex-arm64ec). The fork shipped a second copy (xtajit64-avx.dll) and switched links per game at first; that is not needed, since the module itself reads the variable at start-up, and is not ported.project.pbxprojunchanged.🤖 Generated with Claude Code
Claude-Session: https://claude.ai/code/session_0189oLHghpaYKLk4f786a6bc