Skip to content

patch_and_script_reference

runner edited this page Oct 1, 2026 · 30 revisions

Patch & Script Reference

Complete reference for all patches and scripts in the Endfield_FineWine project. This document serves as the technical index for the compatibility layer that enables Arknights: Endfield to run on Apple Silicon macOS via CrossOver Wine.


Table of Contents


Patch Inventory

All patches are stored under patches/ and applied to CrossOver's Wine 11.0 source tree during the build process. The patch set totals ~394 lines across 8 modified files.

Stage 1: macOS-Specific Rosetta Fixes

Location: patches/stage1-macos/
Target: dlls/ntdll/unix/signal_x86_64.c
Purpose: Fix two Rosetta 2 translation bugs that break VMProtect/TenProtect and ACE anti-cheat on Apple Silicon.

Patch File Function Lines Changed Description
0001-rosetta-nop-skip.patch handle_cet_nop() ~45 Adds case 0x1F to decode and skip multi-byte 0F 1F NOP instructions that Rosetta incorrectly faults on. VMProtect emits 23,000+ of these per launch.
0002-rosetta-priv-instr.patch segv_handler() (TRAP_x86_PRIVINFLT) ~30 On Rosetta path, calls is_privileged_instr() to detect mov reg, cr3 and delivers EXCEPTION_PRIV_INSTRUCTION (matching Linux) instead of EXCEPTION_ILLEGAL_INSTRUCTION. Fixes ACE "driver error 13".

Technical Details: Both fixes live in Wine's x86_64 Unix signal handler (signal_x86_64.c). They sit alongside CrossOver's existing handle_cet_nop (for 0F 1E RDSSP NOPs) and emulate_xgetbv hacks.

📖 Deep dive: 12-stage1-protector-fault.md — root cause analysis and prior art (WineHQ Bug 45083).


Stage 2: dw-proton Anti-Cheat Ports

Location: patches/stage2-dwproton/
Origin: Dawn Winery / dw-proton release 11.0-7 (commit b816be489)
Purpose: Port the Linux-proven ACE anti-cheat compatibility patches to CrossOver's Wine tree.

A. ntoskrnl.exe Kernel Backports (17 functions)

Files: dlls/ntoskrnl.exe/{ntoskrnl.c, ntoskrnl.exe.spec, _private.h, sync.c}
Author: Etaash Mathamsetty (based on wine-ntoskrnl project)

# Function Type Purpose
1 KeAcquireGuardedMutex Implement Guarded mutex acquisition for kernel synchronization
2 KeReleaseGuardedMutex Implement Guarded mutex release
3 PsGetProcessSessionId Implement Process session ID query (ACE checks this)
4 PsGetProcessCreateTimeQuadPart Implement Process creation time
5 PsGetThreadProcess Implement Thread → process mapping
6 KeRegisterBugCheckCallback Stub Bug check callback registration
7 KeRegisterBugCheckReasonCallback Stub Bug check reason callback
8 KeDeregisterBugCheckReasonCallback Stub Deregister bug check callback
9 MmGetVirtualForPhysical Semi-stub Physical → virtual address translation
10 PsGetProcessImageFileName Implement Exact blocker from WineHQ Bug 59411
11 SeLocateProcessImageName Implement Locate process image name
12 PsReferencePrimaryToken Implement Primary token reference
13 PsGetContextThread Implement Thread context (no arch guard)
14 create_process_object fix Fix Process object creation fix in ntoskrnl.c
15 SeLocateProcessImageName follow-up Fix Additional fix
16 KeCapturePersistentThreadState Stub Persistent thread state capture
17 MmGetPhysicalMemoryRanges Implement Physical memory ranges
18 PsGetProcessPeb Implement Process PEB pointer

⚠️ Note: The create_process_object fix (0014) is the only process-creation patch and most likely to conflict with CrossOver's tree.

B. KiUser*Dispatcher int3 Spoof

File: dlls/kernel32/module.c
Authors: Ziia Shi (spoof), NelloKudo (gate)

# ifdef __x86_64__

static BOOL needs_int3_hack(void) {
    // Matches Endfield.exe OR EM-Win64-Shipping.exe
    // Force-enable: PROTON_ENABLE_INT3_HACK=1
}
static void __attribute__((naked)) int3_stub(void) {
    asm("int3\n\tint3\n\tint3\n\tint3\n\t");
}
// In get_proc_address():
if (needs_int3_hack() &&
    (strcmp(function,"KiUserApcDispatcher")==0 ||
     strcmp(function,"KiUserCallbackDispatcher")==0)) {
    return (FARPROC)&int3_stub;
}

# endif

```python

**Mechanism:** ACE's tpshell protector resolves `KiUserApcDispatcher`/`KiUserCallbackDispatcher` via `GetProcAddress` to hook them. Returning a 4×`int3` (`0xCC`) stub defeats the probe. **Guarded by `#ifdef __x86_64__`** — only compiles in x86_64 Wine (Rosetta path).

#### C. `NtDelayExecution` QPC Timing Loop

> **File:** `dlls/ntdll/unix/sync.c`  
> **Author:** Etaash Mathamsetty

```c
else if (timeout->QuadPart < 0) {  // relative wait
    timeout_t when = -timeout->QuadPart, diff;
    LARGE_INTEGER now;
    NtQueryPerformanceCounter(&now, NULL);
    when += now.QuadPart;
    for (;;) {
        NtQueryPerformanceCounter(&now, NULL);
        diff = (when - now.QuadPart + 9) / 10;  // QPC 100ns → µs
        if (diff <= 0) break;
        struct timeval tv = { diff / 1000000, diff % 1000000 };
        if (select(0, NULL, NULL, NULL, &tv) != -1) break;
    }
}
```sql

**Purpose:** ACE performs timing-sensitive checks. Replaces `NtQuerySystemTime`-based sleep with high-resolution QPC busy-wait to avoid anti-cheat timeouts.

#### D. Auxiliary Patches (Ported but Not ACE-Critical)

| Patch | File | Purpose |
|-------|------|---------|
| `wdfldr.sys` stubs (3 patches) | `dlls/wdfldr/` | WDF loader stubs for driver framework |
| `KeGetCurrentIrql` stub | `dlls/ntoskrnl.exe/` | IRQL query stub |
| `NtUserEnableMouseInPointer` fix | `dlls/win32u/` | Mouse-in-pointer fix |
| `VersionService.exe` timing hack | `dlls/kernelbase/` | Process-gated delay (like int3 gate) |
| `winex11` overlay skip | `dlls/winex11/` | **X11-only, macOS-irrelevant** |
| `ntdll` stop unwinding on AV | `dlls/ntdll/` | Access violation unwind fix |

> 📖 **Full inventory with verbatim code:** [02-dwproton-ace-patches.md](02-dwproton-ace-patches.md)

---

### MoltenVK Patches (Experimental Vulkan)

> **Location:** `patches/moltenvk/`  
> **Origin:** Ported from [mary-ext/crossover-wine-endfield](https://github.com/mary-ext/crossover-wine-endfield)  
> **Purpose:** Fix Vulkan renderer issues (swapchain recreation, GPU hangs, TAAU artifacts) when running Endfield with `-force-vulkan`.

| Patch | Fixes |
|-------|-------|
| Swapchain recreation black screen | MoltenVK 1.4.2+ fixes this; patch backports to CrossOver's bundled version |
| Snowy Forest GPU hang (WindowServer kill) | Prevents macOS from killing WindowServer on GPU timeout |
| TAAU/FSR3 artifacts near Recycling Stations | Rendering correctness |
| Pipeline cache staleness | Requires manual `vulkan_pso_cache.bin` deletion after MoltenVK upgrade |

**Usage:** Build with `scripts/build-moltenvk.sh` (needs full Xcode), install via `scripts/package.sh` + `scripts/apply-modules.sh`. Launch with `GFXARGS=-force-vulkan scripts/launch-endfield.sh`.

> 📖 **Details:** [graphics-performance.md#experimental-the-vulkan-renderer](graphics-performance.md#experimental-the-vulkan-renderer) | [troubleshooting.md#in-game-graphics](troubleshooting.md#in-game-graphics)

---

## Script Reference

All scripts live in [`scripts/`](../scripts/) and are executable Bash scripts. Run from the repository root.

### Build Scripts

#### `build-wine.sh` — Main Build Orchestrator

```bash
./scripts/build-wine.sh <stage>
```bash

| Stage | Description | Duration (M4 Pro) |
|-------|-------------|-------------------|
| `deps` | Install Homebrew dependencies (bison, mingw-w64, meson, pkg-config, etc.) | ~2 min |
| `fetch` | Download CrossOver 26.3 Wine source (~142 MB), git-init it | ~1 min |
| `apply` | Apply all 24 patches (verified clean apply) | ~30 sec |
| `configure` | Configure 64-bit-only build under `arch -x86_64` | ~2 min |
| `build` | Compile with `make -j$(sysctl -n hw.ncpu)` | ~10–20 min |
| `all` | Run all stages sequentially (default) | ~15–25 min |

**Environment Variables:**
```bash
export CROSSOVER_VERSION=26.3        # Must match installed CrossOver
export WINE_SRC_DIR=build/wine-src   # Source directory
export BUILD_DIR=build/wine-build64  # Build output
```bash

**Key Implementation Details:**
- Builds **64-bit-only Wine** (no `win32on64`, no `cx-llvm` needed — Endfield is 64-bit only)
- Runs under `arch -x86_64` (Rosetta host) to produce x86_64 binaries
- Minimal configuration: `--disable-tests --without-alsa --without-capi --without-dbus ... --without-x`
- Output: `build/wine-build64/dlls/ntdll/ntdll.so`, `dlls/kernel32/.../kernel32.dll`, `dlls/ntoskrnl.exe/.../ntoskrnl.exe`

> 📖 **Full build docs:** [04-building-crossover-wine.md](04-building-crossover-wine.md) | [scripts/README.md](../scripts/README.md)

#### `build-moltenvk.sh` — MoltenVK Build (Experimental)

```bash
./scripts/build-moltenvk.sh
```bash

- Requires **full Xcode** (not just CLT) for Metal shader compilation
- Builds patched MoltenVK from `patches/moltenvk/`
- Output staged for `package.sh` + `apply-modules.sh`

---

### Deployment Scripts

#### `swap-into-crossover.sh` — Deploy Patched Modules into CrossOver

```bash
./scripts/swap-into-crossover.sh [options]
```bash

**What it does:**
1. Copies `/Applications/CrossOver.app` → staging area (`$TMPDIR/CrossOver_patched.app`)
2. Backs up original modules as `.cxorig`
3. Copies 3 patched modules:
  - `ntdll.so` → `lib/wine/x86_64-unix/ntdll.so`
  - `kernel32.dll` → `lib/wine/x86_64-windows/kernel32.dll`
  - `ntoskrnl.exe` → `lib/wine/x86_64-windows/ntoskrnl.exe`
4. **Injects rpath** into `ntdll.so`: `install_name_tool -add_rpath "@loader_path/../../../lib64"`
5. **Ad-hoc re-signs** swapped modules + outer bundle (preserves CodeWeavers entitlements)
6. Verifies signature: `codesign --verify --deep --strict`
7. Moves to `/Applications/CrossOver_Endfield_Patch.app`

**Options:**
```bash
GPTK_DIR="/Volumes/GPTK/redist/lib/external" ./scripts/swap-into-crossover.sh  # Install GPTK4 D3DMetal
SKIP_GPTK=1 ./scripts/swap-into-crossover.sh                                    # Skip GPTK, use bundled 3.0
```bash

**Critical:** The rpath injection is mandatory — without it, `cxcompatdb.so` fails to load `libgnutls.30.dylib`, D3DMetal backend never activates, and DX11 device creation fails with `80004005`.

> 📖 **Verified recipe & code-signing deep dive:** [05-swapping-into-crossover.md#verified-recipe-2026-09-crossover-2620--macos-270--m4](05-swapping-into-crossover.md#verified-recipe-2026-09-crossover-2620--macos-270--m4)

#### `create-bottle.sh` — Create/Update Game Bottle

```bash
./scripts/create-bottle.sh          # Create new "Arknights Endfield" bottle
UPDATE=1 ./scripts/create-bottle.sh # Update existing bottle settings
```bash

**Bottle Configuration (written to `cxbottle.conf`):**
| Setting | Key | Value |
|---------|-----|-------|
| Windows Version | — | Windows 11 64-bit |
| Graphics Backend | `CX_GRAPHICS_BACKEND` | `d3dmetal` |
| DLSS (MetalFX) | `D3DM_ENABLE_METALFX` | `1` |
| MSync | `WINEMSYNC` | `1` |
| High Resolution Mode | — | **Disabled** (causes white screen

Clone this wiki locally