Fix UTF-8 BOM in INI file writes causing Skyrim resolution issues by cashcon57 · Pull Request #2894 · wabbajack-tools/wabbajack (original) (raw)
Problem
When Wabbajack writes profile INI files during installation (e.g. SkyrimPrefs.ini, SSEDisplayTweaks.ini, user.settings), it uses .NET's Encoding.UTF8 which emits a byte order mark (BOM) — the 3-byte prefix EF BB BF — at the start of the file.
Skyrim's INI parser has trouble reading sections that immediately follow a BOM. Specifically, when [Display] is the first section in the file, the BOM bytes corrupt the section header, causing display settings like iSize W and iSize H to be silently ignored. The game falls back to default resolution (typically 1920x1080) regardless of what the INI file specifies.
This was confirmed through testing reported in #2786:
- Source installation (no BOM) → resolution works correctly
- Wabbajack installation (BOM) → resolution ignored
- Wabbajack installation, INIs manually re-saved without BOM → resolution works correctly
The reason this doesn't affect every modlist is that modlists where [Display] is not the first section happen to dodge the issue — the BOM corrupts a different section header that Skyrim doesn't care about as much.
Fix
Replace Encoding.UTF8 with new UTF8Encoding(false) in all file-writing code paths that produce INI or text files. The false parameter tells .NET not to emit the BOM preamble, while still writing valid UTF-8.
Changed locations:
StandardInstaller.cs— 3parser.WriteFile()calls that write game profile INIs (*prefs.ini,SSEDisplayTweaks.ini, Witcher 3user.settings). These are the direct cause of the reported bug.IniExtensions.cs—SaveIniFile()which writesModOrganizer.iniand.metafiles. MO2 handles both encodings fine, but there's no reason to emit a BOM here either.AbsolutePathExtensions.cs— 2WriteAllLinesAsync()overloads used for writing meta files and other text content.
All of these were using Encoding.UTF8 which is a well-known .NET quirk — the static property returns an encoder that includes a BOM preamble. The UTF8Encoding(false) constructor is the standard workaround.
Testing
I don't have a Windows machine to test the full installation flow end-to-end, but the change is mechanical and narrow in scope — each location simply adds an explicit encoding parameter that suppresses the BOM. No read paths are affected, and no code in the codebase checks for or depends on BOM presence when reading files.
Fixes #2786