Requested by Cameron · project thread
Problem
Slay the Spire 2 played music and showed its cursor on a black screen. Godot's
swap_chain_resize failed every frame with DXMT's own "Not implemented" from
CreateSwapChainForComposition, even though dcomp.dll had logged that it
pointed that vtable slot at composition_swap_chain.
The factory's vtable lives in dxgi.dll's JIT-pool copy. VirtualProtect on that address changes the PE view's page and copies the PE page over the pool copy (virtual_ios.c, "iOS JIT IAT sync: full copy"), once on the way to read/write and again on the way back. The slot was written only in the pool copy, so the second copy put DXMT's entry back. The log shows both syncs of that page around the patch.
Change
build/dcomp/dcomp.c: pe_view() finds the PE view's address of the slot
(the pool copy starts with the same DOS and file headers at the same offset).
The hook is written there and in the pool copy, and the slot is read back after
the protection is restored; the log line says whether the patch stayed.
app/Madeira/arm64ec-windows/dcomp.dll is rebuilt from it with llvm-mingw
20260421. The unchanged source rebuilds to the same code as the committed DLL,
apart from debug paths.
Testing
- On device (iPhone, sideloaded build): Slay the Spire 2 shows its picture
and plays. The game also needs launch settings for the JIT pool and .NET
(
env.DOTNET_EnableWriteXorExecute = 0and others); those are per-game settings, not part of this PR. - This branch: main c2c1b03a has the same dcomp.c and dcomp.dll this commit started from, so it applies unchanged.
🤖 Generated with Claude Code