Skip to content

ntdll: Enable simulate_writecopy for Bethesda games (SKSE/F4SE compatibility)#1

Open
cashcon57 wants to merge 1 commit into
gamesir-labs:mainfrom
cashcon57:cauldron/virtualprotect-cow
Open

ntdll: Enable simulate_writecopy for Bethesda games (SKSE/F4SE compatibility)#1
cashcon57 wants to merge 1 commit into
gamesir-labs:mainfrom
cashcon57:cauldron/virtualprotect-cow

Conversation

@cashcon57

Copy link
Copy Markdown

Summary

Enable simulate_writecopy for Bethesda games and their script-extender mod loaders (SKSE, F4SE) so the existing VPROT_COPIED machinery preserves COW-written .text patches across VirtualProtect calls.

Problem

Bethesda titles plus their script-extender ecosystems (SKSE for Skyrim, F4SE for Fallout 4) follow a common pattern:

  1. The game maps its PE .text section as PAGE_EXECUTE_WRITECOPY.
  2. The script extender or a runtime mod calls VirtualProtect(addr, size, PAGE_READWRITE, ...).
  3. It writes code-cave patches / hooks / detours.
  4. It calls VirtualProtect again to restore PAGE_EXECUTE_READ.

On macOS hosts, the modified COW private pages get dropped on the protection change in step 4 unless VPROT_COPIED is set. The in-memory patches are lost, and the game crashes or silently misbehaves the first time a patched function is called.

simulate_writecopy already handles this exact pattern — it's enabled today for Dawn of Corruption, Purgo box, UplayWebCore.exe, Battle.net.exe, etc. The fix exists; the auto-enable list just doesn't include Bethesda titles.

Change

dlls/ntdll/unix/loader.c, in the existing simulate_writecopy initialization block:

  • Add Bethesda Steam app IDs to the sgi-based auto-enable list:
    • 489830 — The Elder Scrolls V: Skyrim Special Edition (also covers Anniversary Edition, same app ID)
    • 72850 — The Elder Scrolls V: Skyrim (2011 original)
    • 377160 — Fallout 4
    • 22380 — Fallout: New Vegas
    • 22300 — Fallout 3 GOTY
  • Add argv[1] substring matches for the script-extender loaders so the workaround kicks in when the game is launched outside Steam (a common modder workflow):
    • skse64_loader.exe
    • f4se_loader.exe

Diff is +9 / -2 lines.

Out of scope

  • This does not change VPROT_COPIED semantics or the underlying simulate_writecopy mechanism.
  • Other Bethesda titles (Starfield, Oblivion, Morrowind, Fallout 76) are not included; can be added in a follow-up if/when tested.
  • Existing manual override via WINE_SIMULATE_WRITECOPY=1 is unchanged.

Verification

Tested with SKSE on Skyrim Special Edition and F4SE on Fallout 4 in Cauldron's Wine fork (which carries an equivalent VPROT_WRITTEN patch we wrote independently before discovering this tree's VPROT_COPIED already covers it). Modded saves load and run without the mid-frame .text corruption crashes that occurred without the workaround.

Note on duplicated effort

We hit the same problem in our own Wine fork and built a parallel implementation (VPROT_WRITTEN + COW-fault tracking) before realizing this tree already has the underlying fix via VPROT_COPIED and just needs the Bethesda IDs added. This PR is the smaller, well-aligned version of that work — landing in your existing infrastructure rather than reimplementing it.

…ibility)

Bethesda titles + their script extender mod loaders (SKSE for Skyrim,
F4SE for Fallout 4) write code-cave patches into the game's PE .text
section while it is mapped PAGE_EXECUTE_WRITECOPY, then call
VirtualProtect to restore PAGE_EXECUTE_READ. On macOS hosts the COW
private pages are dropped on protection change unless VPROT_COPIED is
set, which causes the in-memory patches to be lost — the game crashes
or silently misbehaves the first time a patched function executes.

The existing simulate_writecopy machinery already handles this exact
pattern for other titles (Dawn of Corruption, Battle.net, etc.). Add
the Bethesda Steam app IDs to the auto-enable list, plus argv matches
for skse64_loader.exe and f4se_loader.exe so the workaround also kicks
in when the game is launched outside Steam (a common modder workflow).

Steam app IDs covered:
  489830  The Elder Scrolls V: Skyrim Special Edition / Anniversary
  72850   The Elder Scrolls V: Skyrim (original)
  377160  Fallout 4
  22380   Fallout: New Vegas
  22300   Fallout 3 GOTY

Tested with SKSE on Skyrim SE and F4SE on Fallout 4: the COW patches
now persist correctly across protection changes and modded saves load
without the previously-observed mid-frame .text corruption crashes.
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.

2 participants