Skip to content

feat: add MetalSharp Wine EAC Linux substrate - #397

Merged
aaf2tbz merged 9 commits into
mainfrom
feat/eac-linux-substrate
Aug 10, 2026
Merged

feat: add MetalSharp Wine EAC Linux substrate#397
aaf2tbz merged 9 commits into
mainfrom
feat/eac-linux-substrate

Conversation

@aaf2tbz

@aaf2tbz aaf2tbz commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add the requested per-game EAC launch surface without changing the proven MetalSharp Wine 11.5 substrate contract. The card toggle remains explicit, per-game, and opt-in; it affects only the next MetalSharp Wine launch.

Changes

  • Keep the existing Darwin-side Linux ELF substrate in src/anticheat/linux_substrate.c; its per-launch maps path follows the app-specific substrate log directory.
  • Add Rust /eac/status and /eac/toggle routes with atomic per-app state at ~/.metalsharp/sharp-library/eac/<appid>.json.
  • Inject the substrate, MetalSharp ELF symbol image, per-game substrate log path, maps path, and module-dump path into the exact MetalSharp Wine launch environment only when the card toggle is enabled.
  • Apply the environment to M9/M10/M11/M12/M32/plain-Wine launch paths and custom Wine launches; GPTK launch code never receives the EAC substrate.
  • Route an opted-in non-Wine request to the already-installed M12 MetalSharp Wine 11.5 lane. An explicit M11 request remains M11; no other Wine build, GPTK, VKMT, or macOS Steam is substituted.
  • Add the EAC toggle immediately to the right of Steam Emu on installed game cards. It is disabled until both packaged native artifacts are present and never starts a game automatically.
  • Add eac_exe_names alongside normal exe_names so the toggle selects each game's existing protected launcher only when enabled. Turning the toggle off emits no EAC environment and uses the normal rule path.
  • Add validated M11 defaults and executable rules for all 36 requested Steam app IDs: Outlast Trials, Halo MCC, Sea of Thieves, Pavlov, Vermintide 2, Watch Dogs 2, Fall Guys, Friday the 13th, VRChat, Rogue Company, Total Lockdown (1121710), Lost Ark, Gears 5, For Honor, REMATCH (2138720), Stay Out, Back 4 Blood, Lords of the Fallen, Throne and Liberty, Star Wars: Squadrons, NBA 2K26, Next Day: Survival, Suicide Squad, SCP: ReEnter (4088120), Killing Floor 3, ARC Raiders, MultiVersus, plus the existing rules for Rocket League, Rust, 7 Days to Die, Hunt, Apex, Halo Infinite, Battlefield 2042, and Squad.
  • Keep Elden Ring and ARMORED CORE VI FIRES OF RUBICON on their existing M12 rules. Fires of Rubicon now uses its real Game/start_protected_game.exe when EAC is enabled; all launch-time protected-executable rename/copy/restore bypass code is removed.
  • Make both substrate artifacts a hard package contract: CMake must generate the ELF image, native/package/bundle/DMG gates require the x86_64 Mach-O + x86-64 ELF pair, and the release/PR workflows run the native package gate.
  • Install the verified pair after the scripts/tools bundle into ~/.metalsharp/runtime/eac/ with an atomic pair replacement and idempotent SHA refresh.
  • Harden both updater implementations to reject incomplete or wrong-architecture app bundles before replacement, retain a rollback backup during installation, and set the post-update migration marker only after a valid app is installed.
  • Bump migration schema to 5. Missing/invalid durable EAC assets now force repair on macOS; migration verifies the pair after reinstall and preserves per-game EAC toggle JSON under sharp-library.
  • Document the card flow, rule coverage, protected executable selection, install/update/migration lifecycle, exact Wine route, and per-app logs.

PR Readiness (MANDATORY)

  • Compatibility verified with at least one real game (game + launch method noted below)
  • No hardcoded paths, secrets, or absolute /Users/... paths introduced
  • Config/rules TOML validated if configs/mtsp-rules.toml or DLL maps changed
  • Version triple (CMakeLists.txt, Cargo.toml, package.json, package-lock.json) in sync if version bumped
  • Bottle/runtime migration and launch behavior preserved (rollback plan noted if changed)
  • Docs / compatibility matrix updated for user-facing changes
  • Regression test added for each bug fix

Local toolchain

  • cargo fmt --all -- --check
  • cargo clippy --all-targets -- -D warnings
  • cargo build --release
  • cargo test — 762 passed
  • python3 tools/ci/validate-rules-toml.py — 734 overrides valid
  • Requested-game rule test — all 36 IDs have M11/M12 defaults, normal executable metadata, protected executable metadata, and route diagnostics
  • EAC-off resolver/env tests — no substrate environment and no protected executable mutation
  • CMake Release configure/build with BUILD_TESTS=ON; EAC substrate and ELF symbol-image targets built
  • tools/bundles/verify-native-shims.sh --eac-only app/native — clean-build EAC contract passed (real x86_64 Mach-O substrate and x86-64 ELF image)
  • ctest --test-dir build-native --output-on-failure -E '^(metal_device|dxbc|format_translation|phase17)$' — 27/27 passed
  • tools/package/prepare-native-placeholders.sh — EAC artifacts are never replaced by placeholders
  • Synthetic metalsharp-scripts-tools.tar.zst passed tools/bundles/verify-bundles.sh, including EAC type/architecture checks
  • python3 -B tools/ci/verify-dmg-workflow.py
  • python3 -B -m py_compile for updater/bundle/workflow helpers
  • tools/ci/shellcheck.sh
  • npm run build
  • git diff --check
  • No new files added at the repository root

Test notes

Real test subject: Elden Ring on the external Steam library, launched explicitly from its real Game/Start_protected_game.exe path. The proof used only the exact installed MetalSharp Wine 11.5 executable, not GPTK, VKMT, another Wine build, Steam auto-run, or a vendor-module replacement.

Proof command:

python3 tools/anticheat/run_eac_proof.py --game-dir '/Volumes/AverySSD/SteamLibrary/steamapps/common/ELDEN RING/Game' --timeout 30

Latest direct proof after rebuilding the substrate:

  • ok: true, proof level real_eac_linux_module_relocated_initialized_exported.
  • Real 9,168,824-byte ELF64 x86-64 EAC module loaded; SHA-256 4fdb6412....
  • EAC requested linux64, received CDN response 200, and logged Wine 11.5.
  • RELA and PLT relocation completed; all six constructors ran; PT_LOAD protections applied; exports a, b, c, and d resolved; EAC_PROOF export_a_success=1 recorded.
  • Exact Wine SHA-256: e621bf88dd07872b391198aee50bf1503fe18d43b7a9c0183fa23075efc61395.
  • Rebuilt substrate SHA-256: 6a75af0317120099d0dd5a88e1d6d0be55f030e48d104015b7763261b3184276.
  • ELF symbol image SHA-256: d8c1008d0ddf70287023c9d4b16840fb0dd4039ae055bff0a10a400f1ebb9886.
  • residualWineProcesses: [] after the enforced 30-second termination and exact wineserver/helper cleanup.

The launch proof intentionally reports protectedGameTransitionObserved: false and onlineSessionObserved: false: it proves the real EAC module load/relocation/constructor/export surface through MetalSharp Wine 11.5 -> macOS, but does not claim an online session or protected-game handoff without a live Steam user.

Card-toggle integration probe (no game launch):

  • /eac/status reported available: true, enabled: false before the toggle.
  • /eac/toggle changed one temporary app id to active: true; disabling it restored active: false.
  • A dry-run requested with pipeline=d3dmetal resolved to pipeline: m12, reported EAC_SUBSTRATE: true, and included DYLD_INSERT_LIBRARIES, METALSHARP_EAC_SUBSTRATE_LIBC, METALSHARP_EAC_SUBSTRATE_LOG, METALSHARP_EAC_SUBSTRATE_MAPS, and METALSHARP_EAC_MODULE_DUMP.
  • The new rules were sourced from the installed SteamCMD app-info records and checked against SteamDB configuration metadata; no requested game was installed or launched.

Install/update/migration checks (no game launch):

  • Installer order places EAC Substrate after Scripts and Tools; the installer requires both archive entries and rejects invalid/ARM-only artifacts.
  • The pair installer is idempotent, refreshes changed sources together, and retains the previous pair when source validation fails.
  • Migration tests prove missing EAC assets request repair, final migration readiness rejects an incomplete pair, and per-game toggle state survives runtime cleanup.
  • Updater and DMG checks reject missing, non-Mach-O, non-x86_64, non-ELF64, or non-x86-64 EAC artifacts before app replacement.

Risk and rollback

The EAC substrate is opt-in and not attached to ordinary launches or Steam auto-run. It does not modify the protected EAC binary, rename/copy game executables, spoof identity exports, or use GPTK. The updater keeps the old app at a temporary rollback path until the new bundle verifies; migration retains user settings and EAC toggle JSON while rebuilding the deleted runtime tree. Revert 4ca8aa44 to remove the per-game rule/launcher-selection surface, 775e00dd and f5b5580c to remove install/update/migration hardening, dd9dfb28 to remove the card toggle and launch integration, and 7217f8fc to remove the substrate implementation.

@aaf2tbz
aaf2tbz merged commit 5afc4ed into main Aug 10, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant