# Wine on Nix — notes for EQLogParser This document captures troubleshooting lessons from packaging EQLogParser on Linux with Wine and Nix. It is meant for maintainers and anyone running the app outside Bottles/Flatpak. For day-to-day usage, see [eqlogparser.md](./eqlogparser.md). The reference implementation is [packages/eqlogparser/package.nix](../packages/eqlogparser/package.nix), which mirrors the upstream [Bottles manifest](https://github.com/kauffman12/EQLogParser/blob/master/bottles/Games/eqlogparser.yml). --- ## What EQLogParser needs under Wine EQLogParser is a **.NET 8 WPF** Windows app. Under Wine that implies: | Requirement | Why | |-------------|-----| | **64-bit Wine prefix** (`WINEARCH=win64`) | Release builds are x64 ([`bottles/Games/eqlogparser.yml`](https://github.com/kauffman12/EQLogParser/blob/master/bottles/Games/eqlogparser.yml)) | | **wine-mono** in the prefix | Wine’s `mscoree` shim; without it you get the interactive *“Wine could not find a wine-mono package”* dialog | | **.NET Desktop Runtime 8 (x64)** | WPF needs the *desktop* runtime, not plain `dotnet-runtime` or wine-mono alone | | **GDI D3D renderer** | WPF on Wine is unstable with default GL/Vulkan paths; Bottles sets `renderer=gdi` | | **No DXVK / VKD3D** | Bottles explicitly disables them for this app | | **Piper TTS installer** (recommended) | Wine x64 cannot use Windows SAPI voices; use `EQLogParser-install-pipertts-*.exe` | The app also expects **`WINELOADER`** to be set so it disables hardware acceleration (software rendering only). See upstream `EQLogParser/App.xaml.cs` — this matches [Linux known issues](https://github.com/kauffman12/EQLogParser/blob/master/website/documentation.md#known-issues-with-linux). --- ## Choosing a Wine package in nixpkgs nixpkgs exposes several Wine variants. They are **not** interchangeable for this project. | Package | Use for EQLogParser? | Notes | |---------|----------------------|-------| | `pkgs.wine64` | **No** (alone) | Often breaks during `wineboot` / `winetricks` (`syswow64\rundll32.exe` / `ntdll.dll` errors). Prefix may be half-initialized. | | `pkgs.wineWow64Packages.stableFull` | **Yes** | WOW64 + `embedInstallers = true` bundles **wine-mono** and gecko MSIs under `share/wine/mono/`. This is what the flake uses. | | `pkgs.wine` (default 32-bit WOW) | **No** | Wrong architecture for a win64-only bottle. | | `pkgs.wine64Packages.full` | **Maybe** | Has `embedInstallers`, but lacks the 32-bit side WOW64 often needs for installers and `msiexec`. Prefer `wineWow64`. | **Rule of thumb:** match Bottles — **64-bit bottle, Wine runner, no DXVK**. On Nix that is `wineWow64Packages.stableFull` with no DXVK in `PATH` or `WINEDLLOVERRIDES`. ```nix wine = pkgs.wineWow64Packages.stableFull; ``` Verify mono is present: ```bash ls "$(nix-build '' -A wineWow64Packages.stableFull --no-out-link)/share/wine/mono/" # e.g. wine-mono-10.0.0-x86.msi ``` --- ## wine-mono vs .NET Desktop Runtime These solve **different** problems. Installing only one leads to confusing errors. ### wine-mono - Ships with Wine when `embedInstallers = true` (`stableFull`, `full` variants). - Installed **into the prefix** via MSI, e.g. `wine msiexec /i "$WINE_PKG/share/wine/mono/wine-mono-"*.msi /qn` - Satisfies Wine’s .NET Framework / `mscoree` path and stops the mono download dialog. - **Not** a substitute for .NET 8. ### .NET 8 Desktop Runtime - Microsoft installer, same as Bottles dependency `dotnetcoredesktop8` ([`dotnetcoredesktop8.yml`](https://github.com/bottlesdevs/dependencies/blob/main/Essentials/dotnetcoredesktop8.yml)). - For win64 bottles, the **x64** installer is enough (Bottles also installs x86; we only install x64). - Example (version pinned in the package): `windowsdesktop-runtime-8.0.12-win-x64.exe /quiet` - Winetricks verb `dotnetdesktop8` is equivalent but failed in our tests (see below). ### Install order (important) ``` 1. wineboot -u 2. wine-mono MSI (/qn) 3. .NET Desktop Runtime (/quiet) 4. renderer=gdi (registry) 5. EQLogParser installer (/VERYSILENT …) ``` Installing EQLogParser or the .NET runtime **before** mono triggers the mono dialog and can leave a broken prefix. --- ## Mapping Bottles settings to Nix/Wine | Bottles (`eqlogparser.yml` + deps) | Nix / shell equivalent | |-----------------------------------|-------------------------| | `Arch: win64` | `export WINEARCH=win64` | | `Runner: Wine`, `dxvk: false`, `vkd3d: false` | `wineWow64Packages.stableFull`; do not add DXVK to the environment | | `dotnetcoredesktop8` | `windowsdesktop-runtime-8.0.12-win-x64.exe /quiet` | | `allfonts` | Copy Nix font packages into `drive_c/windows/Fonts`, register them, and avoid `winetricks allfonts` | | `renderer=gdi` | `wine reg add 'HKCU\Software\Wine\Direct3D' /v renderer /t REG_SZ /d gdi /f` | | Piper TTS installer | `EQLogParser-install-pipertts-*.exe` with Inno flags | | (implicit) wine-mono | `msiexec` on bundled `wine-mono-*.msi` | Inno Setup silent flags used successfully: ```text /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- ``` --- ## Prefix location and mutability ### Do not use `/nix/store` as `WINEPREFIX` during setup Wine refuses to create a configuration directory when ownership checks fail: ```text wine: '/nix/store' is not owned by you, refusing to create a configuration directory there ``` This happens if: - `WINEPREFIX` points at `$out` before copy, or - `HOME` is unset and defaults under `/nix/store`. **Build-time prefix in the Nix store:** possible in theory (build under `$NIX_BUILD_TOP`, then `cp` to `$out`), but the EQLogParser package uses **first-run setup** in `$XDG_DATA_HOME/eqlogparser/wine` instead — simpler and avoids sandbox/fontconfig/XDG issues. ### Recommended layout | Variable | Value | |----------|--------| | `WINEPREFIX` | `$XDG_DATA_HOME/eqlogparser/wine` (or `~/.local/share/eqlogparser/wine`) | | `HOME` | User’s real home (or a writable temp dir during one-off setup) | | `WINEARCH` | `win64` | | `WINELOADER` | Path to `wine` binary (EQLogParser uses this to detect Wine) | Reset a bad prefix: ```bash rm -rf ~/.local/share/eqlogparser/wine nix run .#eqlogparser ``` --- ## Winetricks on Nix `winetricks` from nixpkgs works, but several verbs failed in testing **even after** a healthy `wineboot` and mono install: ```text warning: wine cmd.exe /c echo '%AppData%' returned empty string ``` Affected verbs included `allfonts`, `renderer=gdi`, and `dotnetdesktop8`. The prefix was usable; winetricks’ `%AppData%` probe was not. **Workarounds:** - **GDI renderer:** set the registry directly (see table above). - **.NET Desktop Runtime:** use Microsoft’s `.exe` from Bottles’ dependency URL, not winetricks. - **Fonts:** copy Nix font packages into `drive_c/windows/Fonts`, register them under the Windows `Fonts` registry key, and set Wine font replacements for common Windows UI fonts. --- ## Graphics: GDI, DXVK, and WPF WPF on Wine is sensitive to the renderer: - Bottles sets **`renderer=gdi`** via winetricks; we set the same registry value. - **Do not enable DXVK/VKD3D** for this app (Bottles `dxvk: false`, `vkd3d: false`). - EQLogParser forces **software rendering** when `WINELOADER` is set. Confirm in logs: `RenderMode: SoftwareOnly` under `…/AppData/Roaming/EQLogParser/logs`. If you see rendering glitches, verify GDI is set: ```bash WINEPREFIX=~/.local/share/eqlogparser/wine wine reg query 'HKCU\Software\Wine\Direct3D' /v renderer ``` --- ## Common errors and fixes ### “Wine could not find a wine-mono package” **Cause:** Prefix has no mono MSI installed, or wrong Wine package (no embedded MSI). **Fix:** 1. Use `wineWow64Packages.stableFull`. 2. Install mono before anything else: `wine msiexec /i "$(wine --prefix 2>/dev/null; echo $WINE_PKG)/share/wine/mono/wine-mono-"*.msi /qn` 3. Or use `nix run .#eqlogparser` and let [package.nix](../packages/eqlogparser/package.nix) run setup. ### `failed to start L"C:\\windows\\syswow64\\rundll32.exe": c0000135` **Cause:** `pkgs.wine64` prefix without proper WOW64 support. **Fix:** Switch to `wineWow64Packages.stableFull` and recreate the prefix. ### App installs but crashes on start / “.NET not found” **Cause:** Desktop Runtime 8 x64 missing (only mono or only ASP.NET runtime installed). **Fix:** Install `windowsdesktop-runtime-8.0.x-win-x64.exe` with `/quiet`. ### `wine cmd.exe` / `%AppData%` empty (winetricks) **Cause:** Known winetricks + Wine prefix quirk on Nix; not always fatal. **Fix:** Avoid winetricks for dotnet/gdi; use direct installers and `reg add`. ### Fontconfig / `XDG_RUNTIME_DIR` during Nix builds **Cause:** Building a Wine prefix inside `runCommand` without a full graphics/font stack. **Fix:** Prefer **runtime** prefix creation (current package design), or add `fontconfig` / `XDG_RUNTIME_DIR` to the builder if you revisit store-time prefixes. --- ## Debugging checklist 1. **Wine version:** `wine --version` (from the wrapped `PATH`). 2. **Prefix arch:** `grep '#arch=' "$WINEPREFIX"/*.reg` → expect `win64`. 3. **Mono installed:** `test -d "$WINEPREFIX/drive_c/windows/mono"` or check Add/Remove in `wine uninstaller`. 4. **.NET 8 desktop:** `ls "$WINEPREFIX/drive_c/Program Files/dotnet/shared/Microsoft.WindowsDesktop.App/8.*"` 5. **App binary:** `test -f "$WINEPREFIX/drive_c/Program Files/EQLogParser/EQLogParser.exe"` 6. **EQLogParser log:** `$WINEPREFIX/drive_c/users/$USER/AppData/Roaming/EQLogParser/logs` 7. **Render mode:** log line should show `SoftwareOnly` under Wine. 8. **Piper TTS:** log should mention `piper-tts` if using the piper installer. Run with more Wine noise: ```bash WINEDEBUG=+pid,+process wine … ``` --- ## Why the package uses first-run setup We tried baking the prefix into the Nix store at build time. Blockers included: - Wine refusing `/nix/store` paths for initial config - Fontconfig and `XDG_RUNTIME_DIR` in the sandbox - Long, brittle builds that still produced prefixes winetricks could not post-process **Current approach:** ship Wine + installers in the store; run `eqlogparser-setup-prefix` on first launch (and on version bumps). Trade-off: first start takes several minutes; later starts are fast. --- ## Manual reproduction (without Nix) Equivalent to Bottles + [upstream manual install docs](https://github.com/kauffman12/EQLogParser/blob/master/website/documentation.md#manually-installing-without-flatpakbottles): ```bash # Use wine-wow64 from your distro or nix shell wineWow64Packages.stableFull export WINEARCH=win64 export WINEPREFIX="$HOME/.local/share/eqlogparser/wine" export PATH="/path/to/wine-wow64/bin:$PATH" wineboot -u wine msiexec /i /path/to/wine-mono-*.msi /qn wine windowsdesktop-runtime-8.0.12-win-x64.exe /quiet wine reg add 'HKCU\Software\Wine\Direct3D' /v renderer /t REG_SZ /d gdi /f wine EQLogParser-install-pipertts-2.3.54.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- export WINELOADER="$(command -v wine)" wine "$WINEPREFIX/drive_c/Program Files/EQLogParser/EQLogParser.exe" ``` --- ## References - [EQLogParser Linux support (website)](https://github.com/kauffman12/EQLogParser/blob/master/website/documentation.md#linux-support) - [Bottles game manifest](https://github.com/kauffman12/EQLogParser/blob/master/bottles/Games/eqlogparser.yml) - [Bottles `dotnetcoredesktop8` dependency](https://github.com/bottlesdevs/dependencies/blob/main/Essentials/dotnetcoredesktop8.yml) - [Wine Mono wiki](https://gitlab.winehq.org/wine/wine/-/wikis/Wine-Mono) - [Nix usage](./eqlogparser.md) - [packages/eqlogparser/package.nix](../packages/eqlogparser/package.nix) — maintained install script