Skip to content

development_setup

runner edited this page Oct 5, 2026 · 15 revisions

Endfield_FineWine Development Documentation

Table of Contents

  1. Overview
  2. Development Environment Setup
  3. Project Structure and Architecture
  4. Coding Standards and Guidelines
  5. CI/CD Pipeline
  6. Build and Release Processes
  7. Testing Procedures
  8. Debugging and Troubleshooting
  9. Contribution Guidelines
  10. Code Review Procedures
  11. Development Tools

Overview

Endfield_FineWine is a compatibility layer that enables Arknights: Endfield to run on Apple Silicon Macs through a custom-patched CrossOver Wine. The project provides patches to fix anti-cheat compatibility, graphics translation, and Rosetta 2 translation issues.

Key Features:

  • Custom Wine patches for ACE anti-cheat compatibility
  • Graphics backend optimization (D3DMetal, DXMT, DXVK)
  • Rosetta 2 signal handling fixes
  • Automated build and deployment scripts

Development Environment Setup

Prerequisites

Component Version Notes
macOS 15 (Sequoia) or newer Tested on 27.0 / 26.5
Hardware Apple Silicon (M-series) Intel not supported
CrossOver 26.3 Licensed version from codeweavers.com
Xcode Command Line Tools Latest xcode-select --install
Homebrew Latest /opt/homebrew for Apple Silicon

Installation Steps

# Install Xcode Command Line Tools

xcode-select --install

# Install Homebrew (if not already installed)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Install required dependencies

brew install bison mingw-w64 meson pkg-config flex

# Install Rosetta 2 (required)

softwareupdate --install-rosetta --agree-to-license
```bash

### Repository Setup

```bash

# Clone the repository

git clone https://github.com/stoicswe/Endfield_FineWine.git
cd Endfield_FineWine

# Verify the setup

./scripts/build-wine.sh deps
```text

## Project Structure and Architecture

### Directory Structure

```yaml
Endfield_FineWine/
├── .github/
│   ├── scripts/
│   │   ├── generate-wiki.py
│   │   └── generate-release-notes.py
│   └── workflows/
│       ├── build.yml
│       ├── nightly.yml
│       └── update-wiki.yml
├── patches/
│   ├── stage1-macos/
│   │   └── signal_x86_64.c.patch
│   ├── stage2-dwproton/
│   │   ├── misc/
│   │   ├── em-backports/
│   │   └── README.md
│   └── README.md
├── scripts/
│   ├── build-wine.sh
│   ├── swap-into-crossover.sh
│   ├── create-bottle.sh
│   ├── launch-endfield.sh
│   └── capture-failure.sh
├── docs/
│   ├── installation.md
│   ├── performance.md
│   ├── troubleshooting.md
│   └── technical.md
├── patcher-app/
│   ├── Sources/
│   │   └── FineWinePatcher/
│   ├── Tests/
│   └── README.md
├── mod-injection/
│   ├── README.md
│   └── 01-xxmi-efmi-mod-loading.md
└── README.md
```bash

### Architecture Overview

The project follows a layered architecture:

1. **Wine Patches Layer**: Custom patches for Rosetta 2 compatibility and ACE anti-cheat
2. **Build System Layer**: Shell scripts for building and deploying patched Wine
3. **Deployment Layer**: Scripts for swapping modules into CrossOver
4. **Application Layer**: FineWine Patcher.app GUI for end-user deployment

## Coding Standards and Guidelines

### Shell Script Standards

```bash

# !/bin/bash

# Always include shebang

set -euo pipefail  # Exit on error, undefined vars, pipe failures

# Use descriptive variable names

BUILD_DIR="${BUILD_DIR:-$PWD/build}"

# Provide helpful error messages

if [[ ! -d "$SOURCE_DIR" ]]; then
    echo "Error: Source directory not found: $SOURCE_DIR" >&2
    exit 1
fi

# Use functions for reusable code

function build_wine() {
    local build_type="${1:-release}"

# Implementation here

}

# Document functions

# Builds Wine with specified configuration

# Arguments:

# $1 - Build type (release/debug)

# Returns:

# 0 on success, non-zero on failure

```python

### Python Script Standards

```python

# !/usr/bin/env python3

"""Generate wiki documentation from markdown files."""

import argparse
import logging
from pathlib import Path
from typing import List

# Configure logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

def generate_wiki(source_dir: Path, output_file: Path) -> None:
    """
    Generate wiki documentation from markdown files.
    
    Args:
        source_dir: Directory containing markdown files
        output_file: Output file path for generated wiki
        
    Raises:
        FileNotFoundError: If source directory doesn't exist
    """
    if not source_dir.exists():
        raise FileNotFoundError(f"Source directory not found: {source_dir}")
    
# Implementation here

    pass

def main() -> None:
    """Main entry point."""
    parser = argparse.ArgumentParser(description="Generate wiki documentation")
    parser.add_argument("--source", type=Path, required=True, help="Source directory")
    parser.add_argument("--output", type=Path, required=True, help="Output file")
    
    args = parser.parse_args()
    
    try:
        generate_wiki(args.source, args.output)
        logger.info("Wiki generation completed successfully")
    except Exception as e:
        logger.error(f"Wiki generation failed: {e}")
        raise

if __name__ == "__main__":
    main()
```python

### Swift Code Standards (patcher-app)

```swift
import Foundation

/// Manages the patching process for CrossOver Wine
final class PatcherEngine {
    /// Applies patches to the specified CrossOver application
    /// - Parameters:
    ///   - source: Source CrossOver application
    ///   - destination: Destination for patched application
    /// - Throws: PatchError if patching fails
    func patch(source: URL, destination: URL) throws {
        // Validate inputs
        guard FileManager.default.fileExists(atPath: source.path) else {
            throw PatchError.sourceNotFound(source)
        }
        
        // Implementation here
    }
}

enum PatchError: LocalizedError {
    case sourceNotFound(URL)
    case invalidConfiguration
    case patchFailed(String)
    
    var errorDescription: String? {
        switch self {
        case .sourceNotFound(let url):
            return "Source file not found: \(url.path)"
        case .invalidConfiguration:
            return "Invalid configuration provided"
        case .patchFailed(let reason):
            return "Patch failed: \(reason)"
        }
    }
}
```python

## CI/CD Pipeline

The project uses GitHub Actions for continuous integration and deployment.

### Workflows

#### Build Workflow (`.github/workflows/build.yml`)

```yaml
name: Build
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Install dependencies
      run: |
        brew install bison mingw-w64 meson pkg-config flex
        softwareupdate --install-rosetta --agree-to-license
    
    - name: Build Wine
      run: ./scripts/build-wine.sh all
    
    - name: Run tests
      run: |

# Test build artifacts

        test -f build/wine-build64/dlls/ntdll/ntdll.so
```yaml

#### Nightly Build Workflow (`.github/workflows/nightly.yml`)

```yaml
name: Nightly
on:
  schedule:
    - cron: '0 0 * * *'  # Daily at midnight
  workflow_dispatch:

jobs:
  nightly:
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Build and package
      run: |
        ./scripts/build-wine.sh all
        ./scripts/swap-into-crossover.sh
    
    - name: Create release
      uses: softprops/action-gh-release@v1
      with:
        files: |
          CrossOver_Endfield_Patch.app
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```bash

#### Wiki Update Workflow (`.github/workflows/update-wiki.yml`)

```yaml
name: Generate Wiki Documentation
on:
  push:
    branches: [ main ]
  workflow_dispatch:

jobs:
  wiki:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
      with:
        fetch-depth: 0
    
    - name: Generate wiki
      run: python .github/scripts/generate-wiki.py
    
    - name: Deploy wiki
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_dir: ./_wiki
```bash

## Build and Release Processes

### Building Wine

```bash

# Full build process

./scripts/build-wine.sh all

# Step-by-step build

./scripts/build-wine.sh deps       # Install dependencies
./scripts/build-wine.sh fetch      # Download CrossOver source
./scripts/build-wine.sh apply      # Apply patches
./scripts/build-wine.sh configure  # Configure build
./scripts/build-wine.sh build      # Compile
```bash

### Deployment Process

```bash

# Deploy to CrossOver

./scripts/swap-into-crossover.sh

# Create game bottle

./scripts/create-bottle.sh
```python

### Release Process

1. **Version Bump**: Update version in relevant files
2. **Changelog**: Update CHANGELOG.md
3. **Build**: Run CI/CD pipeline
4. **Test**: Verify build artifacts
5. **Release**: Create GitHub release with artifacts

```bash

# Manual release process

git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
gh release create v1.0.0 --generate-notes
```bash

## Testing Procedures

**Note**: The project does not have automated tests. Testing is performed manually.

### Manual Testing Checklist

1. **Build Verification**
   ```bash

# Verify build artifacts exist

   test -f build/wine-build64/dlls/ntdll/ntdll.so
   test -f build/wine-build64/dlls/kernel32/kernel32.dll
   test -f build/wine-build64/dlls/ntoskrnl.exe/ntoskrnl.exe
```bash

2. **Patch Application**
   ```bash

# Verify patches were applied

   cd build/wine-src
   git status  # Should show modified files
```bash

3. **Deployment Verification**
   ```bash

# Verify patched CrossOver

   codesign --verify --deep /Applications/CrossOver_Endfield_Patch.app
```bash

4. **Game Launch**
  - Launch CrossOver_Endfield_Patch.app
  - Create "Arknights Endfield" bottle
  - Install Gryphline launcher
  - Launch game with DirectX 11

## Debugging and Troubleshooting

### Common Issues and Solutions

#### CrossOver Damaged Error

```bash

# Re-seal the application

codesign --force --sign - --preserve-metadata=entitlements /Applications/CrossOver_Endfield_Patch.app
```bash

#### White Screen After Game Update

```bash

# Force DirectX 11 mode

# In launcher: dropdown next to Start -> "Launch with DirectX 11"

# Or launch with:

./scripts/launch-endfield.sh
```bash

#### Memory Pressure Freeze

```bash

# Monitor memory usage

vm_stat
memory_pressure

# Kill wineserver if needed

CXR="/Applications/CrossOver_Endfield_Patch.app/Contents/SharedSupport/CrossOver"
WINEPREFIX="$HOME/Library/Application Support/CrossOver/Bottles/Arknights Endfield" CX_ROOT="$CXR" "$CXR/bin/wineserver" -k
```bash

### Debug Logging

```bash

# Enable detailed logging

DEBUG=1 ./scripts/launch-endfield.sh

# Capture failure logs

./scripts/01-capture-failure.sh
```bash

### Log Analysis

```bash

# View recent logs

tail -f ~/endfield-debug/latest/cxlog.txt

# Search for specific errors

grep -i "error" ~/endfield-debug/latest/cxlog.txt
grep -i "failed" ~/endfield-debug/latest/cxlog.txt
```bash

## Contribution Guidelines

### Getting Started

1. Fork the repository
2. Create a feature branch:
   ```bash
   git checkout -b feature/new-feature
```bash
3. Make your changes
4. Commit with descriptive messages:
   ```bash
   git commit -m "feat: Add new feature description"
```bash
5. Push to your fork:
   ```bash
   git push origin feature/new-feature
```bash
6. Create a Pull Request

### Code Style

- Follow existing code patterns
- Use meaningful commit messages
- Include documentation for new features
- Keep changes focused and atomic

### Pull Request Process

1. Ensure all CI checks pass
2. Update documentation if needed
3. Request review from maintainers
4. Address feedback promptly

## Code Review Procedures

### Review Checklist

- [ ] Code follows project conventions
- [ ] Documentation is updated
- [ ] Tests pass (if applicable)
- [ ] No security vulnerabilities
- [ ] Performance considerations addressed
- [ ] Backward compatibility maintained

### Review Process

1. **Automated Checks**: CI runs automatically on PR
2. **Manual Review**: Maintainers review code quality
3. **Testing**: Verify functionality manually
4. **Approval**: Required approvals from maintainers
5. **Merge**: Squash and merge to main branch

### Review Tools

```bash

# Use git to review changes

git diff HEAD~1
git log --oneline -10

# Check for common issues

shellcheck scripts/*.sh
```bash

## Development Tools

### Essential Tools

| Tool | Purpose | Installation |
|------|---------|--------------|
| [Homebrew](https://brew.sh) | Package management | `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"` |
| [Git](https://git-scm.com) | Version control | `brew install git` |
| [Xcode Command Line Tools](https://developer.apple.com/xcode/) | Compiler and tools | `xcode-select --install` |

### Development Utilities

```bash

# Shell scripting tools

brew install shellcheck  # Static analysis for shell scripts

# Python development

brew install python@3.11
pip3 install black mypy flake8  # Code formatting and linting

# Swift development (for patcher-app)

brew install swiftlint  # Swift linting
```python

### Debugging Tools

```bash

# System monitoring

brew install htop  # Process monitoring
brew install watch  # File monitoring

# Network debugging

brew install tcpdump  # Network packet analysis

# Code signing verification

codesign --verify --deep /Applications/CrossOver_Endfield_Patch.app
spctl -a -vv /Applications/CrossOver_Endfield_Patch.app
```python

### IDE Recommendations

- **Visual Studio Code**: Excellent for shell scripts and Python
- **Xcode**: Required for Swift development (patcher-app)
- **Sublime Text**: Lightweight option for quick edits

### Useful Commands

```bash

# Navigate project structure

find . -name "*.sh" -type f | head -10
find . -name "*.py" -type f | head -10

# Check file permissions

ls -la scripts/

# Verify patch application

cd build/wine-src && git diff --stat

# Monitor build progress

make -j$(sysctl -n hw.ncpu) 2>&1 | tee build.log
```bash

---

For more information, see the [project README](../README.md) and [documentation](docs/) directory.

Clone this wiki locally