Burglin' Gnomes: finalize fix, docs, and BepInEx install support
Final tuned values baked in as defaults: HudScale=0.8, WorldLabelScale=0.8. - install.sh gains METHOD=bepinex: installs BepInEx from vendor + the prebuilt plugin, with a matching uninstall that leaves BepInEx/ alone (other mods may depend on it). Success banner is now method-aware. - Ship the prebuilt plugin DLL so users don't need a .NET SDK. - Per-game README documenting why the camera is deliberately untouched (orthographic, constant orthographicSize = already Hor+), the two-canvas UI problem, tuning, and where the plugin log actually lives. - Root README lists both games and both fix methods. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,13 +2,19 @@
|
||||
|
||||
Ultrawide (**32:9 / 21:9**) fixes for PC games that ship with poor or no ultrawide support — built and tested on a **Samsung 49" Odyssey G93SC (5120×1440)**, and **Proton/Linux-first**.
|
||||
|
||||
Most of these force **Hor+ FOV** (a wider screen shows you *more*, instead of zooming the camera in) and disable pillarboxing, by patching the game in memory at runtime with [SUWSF](https://github.com/PhantomGamers/SUWSF) + [Ultimate ASI Loader](https://github.com/ThirteenAG/Ultimate-ASI-Loader).
|
||||
Fixes use whichever approach the engine calls for:
|
||||
|
||||
- **SUWSF + Ultimate ASI Loader** — runtime memory patching, for Unreal titles (and anything DRM-wrapped, where static patching is impossible).
|
||||
- **BepInEx plugin** — a proper C# mod, for Unity titles with the Mono backend.
|
||||
|
||||
Most force **Hor+ FOV** (a wider screen shows you *more* rather than zooming in) and fix UI that assumes 16:9. Some games already render correctly and only need UI work — [Burglin' Gnomes](games/BurglinGnomes/) is one, and the fix deliberately leaves its camera alone.
|
||||
|
||||
## Supported games
|
||||
|
||||
| Game | Engine | Status |
|
||||
|---|---|---|
|
||||
| [Gundam Breaker 4](games/GundamBreaker4/) | Unreal Engine 4.27 | ✅ Confirmed working in gameplay at 5120×1440 |
|
||||
| Game | Engine | Method | Status |
|
||||
|---|---|---|---|
|
||||
| [Gundam Breaker 4](games/GundamBreaker4/) | Unreal Engine 4.27 | SUWSF | ✅ Confirmed working at 5120×1440 |
|
||||
| [Burglin' Gnomes](games/BurglinGnomes/) | Unity 6 (Mono) | BepInEx plugin | ✅ Confirmed working at 5120×1440 |
|
||||
|
||||
## Install
|
||||
|
||||
@@ -32,7 +38,8 @@ Config-file tweaks (e.g. UE4's `AspectRatioAxisConstraint=MaintainYFOV`) typical
|
||||
|
||||
| Path | What |
|
||||
|---|---|
|
||||
| `games/<Game>/SUWSF.ini` | That game's patch definitions |
|
||||
| `games/<Game>/SUWSF.ini` | Patch definitions (SUWSF games) |
|
||||
| `games/<Game>/plugin/` | C# plugin source + prebuilt DLL (BepInEx games) |
|
||||
| `games/<Game>/game.conf` | Game metadata (appid, exe, paths, launch option) |
|
||||
| `install.sh` | Generic installer / uninstaller |
|
||||
| `tools/build_release.sh` | Builds a per-game drop-in release zip |
|
||||
@@ -45,8 +52,9 @@ Config-file tweaks (e.g. UE4's `AspectRatioAxisConstraint=MaintainYFOV`) typical
|
||||
## Adding a game
|
||||
|
||||
1. `mkdir games/<GameName>` with a `game.conf` (copy GB4's as a template) and a `SUWSF.ini`.
|
||||
2. Start from the known UE4 patterns in [`games/GundamBreaker4/SUWSF.ini`](games/GundamBreaker4/SUWSF.ini) — they match across many UE4 titles.
|
||||
3. If a pattern misses, use `tools/dump_decrypted.py` + `tools/aob.py` to derive the game's exact bytes.
|
||||
2. Set `METHOD=` in `game.conf` to `suwsf` or `bepinex`.
|
||||
3. **Unreal:** start from the UE4 patterns in [`games/GundamBreaker4/SUWSF.ini`](games/GundamBreaker4/SUWSF.ini) — they match across many UE4 titles. If a pattern misses, use `tools/dump_decrypted.py` + `tools/aob.py` to derive the exact bytes.
|
||||
4. **Unity:** install BepInEx + UnityExplorer and inspect live with [`tools/unity_diag.cs`](tools/unity_diag.cs) / [`tools/unity_uitune.cs`](tools/unity_uitune.cs), then write a plugin (copy `games/BurglinGnomes/plugin/`).
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,98 @@
|
||||
# Burglin' Gnomes — UltraWide Fix
|
||||
|
||||
✅ **Confirmed working at 5120×1440 (32:9) on Proton.**
|
||||
|
||||
- **Engine:** Unity 6 (6000.0.62f1), Mono backend, URP + Cinemachine
|
||||
- **Steam AppID:** 3844970
|
||||
- **Executable:** `Gnomium.exe`
|
||||
- **Method:** BepInEx plugin (no DRM, no memory patching needed)
|
||||
|
||||
## What it fixes — and what it deliberately doesn't
|
||||
|
||||
**The camera is already correct.** It's *orthographic* with a constant `orthographicSize` of 5.0, so a wider display genuinely shows more world (visible width 17.8 → 35.6 going 16:9 → 32:9). That's textbook Hor+, and this fix does not touch it. `fieldOfView` reads 60 at every resolution simply because orthographic cameras don't use it — a red herring if you go looking.
|
||||
|
||||
**The problem is entirely UI**, in two separate places needing two different levers:
|
||||
|
||||
| Canvas | Problem | Lever |
|
||||
|---|---|---|
|
||||
| HUD (`ScreenSpaceOverlay` + `ScaleWithScreenSize`) | Ships `matchWidthOrHeight = 0.453` (width-biased). At 5120px that yields scaleFactor **1.948** — a ballooned HUD with overlapping bottom/centre text. | `match = 1` (scale by height) + raise `referenceResolution.y`, shrinking the HUD *and* giving the layout more logical room |
|
||||
| In-world labels (`WorldSpace`, e.g. `NamePlate`) | At 32:9 you see twice as much world, so far more labels are on screen and can collide | Canvas `transform.localScale` |
|
||||
|
||||
> **Gotcha:** `CanvasScaler.scaleFactor` does nothing on a WorldSpace canvas — `CanvasScaler.HandleWorldCanvas()` overwrites it with `dynamicPixelsPerUnit` every frame. Scaling the transform is the only thing that works.
|
||||
|
||||
## Install (Linux / Proton)
|
||||
|
||||
```bash
|
||||
./install.sh BurglinGnomes
|
||||
```
|
||||
|
||||
Then **required** — Steam → Properties → Launch Options:
|
||||
|
||||
```
|
||||
WINEDLLOVERRIDES="winhttp=n,b" %command%
|
||||
```
|
||||
|
||||
Without it Proton ignores BepInEx's `winhttp.dll` loader and the plugin never runs.
|
||||
|
||||
## Install (Windows)
|
||||
|
||||
Extract the release zip into the game folder (next to `Gnomium.exe`). No launch option needed.
|
||||
|
||||
## Tuning
|
||||
|
||||
Config is generated on first launch:
|
||||
|
||||
```
|
||||
<game>/BepInEx/config/com.programmingpug.burglingnomes.ultrawidefix.cfg
|
||||
```
|
||||
|
||||
**Edits apply live (~2s) — no restart.** BepInEx doesn't reload config on its own, so the plugin watches the file's mtime and calls `Config.Reload()` itself.
|
||||
|
||||
| Setting | Default | Notes |
|
||||
|---|---|---|
|
||||
| `HudScale` | `0.8` | HUD size. Lower = smaller HUD *and* more layout room (cures overlapping text) |
|
||||
| `WorldLabelScale` | `0.8` | In-world nameplate size |
|
||||
| `MatchWidthOrHeight` | `1.0` | **Leave at 1.** Lower re-introduces width scaling and cramps the layout vertically |
|
||||
| `DesignHeight` | `1080` | The game's design height; don't change |
|
||||
| `Verbose` | `false` | Log every canvas adjustment |
|
||||
|
||||
`HudScale` → resulting HUD scale at 5120×1440 (stock is 1.333):
|
||||
|
||||
| HudScale | 1.0 | 0.85 | **0.8** | 0.6 |
|
||||
|---|---|---|---|---|
|
||||
| scale | 1.333 | 1.133 | **1.067** | 0.800 |
|
||||
|
||||
## Verifying it works
|
||||
|
||||
```
|
||||
<game>/BepInEx/LogOutput.log
|
||||
```
|
||||
|
||||
That's the plugin's log — **not** UnityExplorer's in-game Log window, which only shows Unity `Debug.Log`. You should see:
|
||||
|
||||
```
|
||||
Burglin' Gnomes UltraWide Fix 1.0.0 loaded.
|
||||
HUD 'Canvas' ref (1920.00, 1080.00) -> (1920.00, 1350.00) match=1 => scale=1.067
|
||||
World 'NamePlate' localScale (1.00, 1.00, 1.00) -> (0.80, 0.80, 0.80)
|
||||
```
|
||||
|
||||
If a line is absent, that adjustment didn't happen.
|
||||
|
||||
## Uninstall
|
||||
|
||||
```bash
|
||||
./install.sh BurglinGnomes uninstall
|
||||
```
|
||||
|
||||
Removes the loader and plugin. `BepInEx/` is left in place in case other mods use it.
|
||||
|
||||
## Building the plugin from source
|
||||
|
||||
Prebuilt `BurglinGnomes.UltraWideFix.dll` ships here, so this is only needed if you change it:
|
||||
|
||||
```bash
|
||||
cd plugin
|
||||
dotnet build -c Release -p:GameDir="/path/to/Burglin' Gnomes"
|
||||
```
|
||||
|
||||
Requires the .NET SDK; it references the game's own assemblies and redistributes none of them.
|
||||
@@ -9,7 +9,8 @@ ENGINE="Unity 6 (6000.0.62f1), Mono backend, URP + Cinemachine"
|
||||
# Fix method: BepInEx plugin (not SUWSF — no DRM, managed C# assemblies)
|
||||
METHOD="bepinex"
|
||||
LOADER="winhttp.dll" # BepInEx's Doorstop proxy
|
||||
PLUGIN_DLL="BurglinGnomes.UltraWideFix.dll"
|
||||
LAUNCH_OPTION='WINEDLLOVERRIDES="winhttp=n,b" %command%'
|
||||
|
||||
PREFIX_INI="" # no config-level tweak identified yet
|
||||
STATUS="IN PROGRESS — symptoms: camera zoomed (Vert-) + broken UI at 32:9"
|
||||
STATUS="Confirmed working at 5120x1440 (32:9) — HUD + nameplate scaling"
|
||||
|
||||
@@ -57,14 +57,14 @@ namespace BurglinGnomes.UltraWideFix
|
||||
"Keep at 1 for ultrawide; lower values re-introduce width scaling and " +
|
||||
"cramp the layout vertically.",
|
||||
new AcceptableValueRange<float>(0f, 1f)));
|
||||
_hudScale = Config.Bind("HUD", "HudScale", 0.85f,
|
||||
_hudScale = Config.Bind("HUD", "HudScale", 0.8f,
|
||||
new ConfigDescription(
|
||||
"HUD size multiplier. Below 1 shrinks the HUD AND gives the layout more " +
|
||||
"logical room, which is what cures overlapping text. 1 = stock size.",
|
||||
new AcceptableValueRange<float>(0.4f, 1.5f)));
|
||||
_designHeight = Config.Bind("HUD", "DesignHeight", 1080f,
|
||||
"The game's design reference height. Do not change unless you know why.");
|
||||
_worldScale = Config.Bind("World", "WorldLabelScale", 1.0f,
|
||||
_worldScale = Config.Bind("World", "WorldLabelScale", 0.8f,
|
||||
new ConfigDescription(
|
||||
"Size multiplier for in-world labels (nameplates). At 32:9 you see twice " +
|
||||
"as much world, so more labels are on screen and can collide; lower this " +
|
||||
|
||||
+45
-13
@@ -105,32 +105,58 @@ remove_ini() {
|
||||
fi
|
||||
}
|
||||
|
||||
METHOD="${METHOD:-suwsf}"
|
||||
|
||||
if [ "$ACTION" = "uninstall" ]; then
|
||||
echo "[+] Uninstalling..."
|
||||
for f in SUWSF.asi SUWSF.ini dsound.dll dinput8.dll version.dll winmm.dll; do
|
||||
[ -f "$GAMEDIR/$f" ] && rm -v "$GAMEDIR/$f"
|
||||
done
|
||||
if [ "$METHOD" = "bepinex" ]; then
|
||||
rm -vf "$GAMEDIR/winhttp.dll" "$GAMEDIR/doorstop_config.ini" "$GAMEDIR/.doorstop_version" \
|
||||
"$GAMEDIR/changelog.txt" "$GAMEDIR/BepInEx/plugins/$PLUGIN_DLL"
|
||||
# leave BepInEx/ itself: the user may have other mods installed
|
||||
echo "[i] Left BepInEx/ in place (other mods may rely on it). Delete it manually if unused."
|
||||
else
|
||||
for f in SUWSF.asi SUWSF.ini dsound.dll dinput8.dll version.dll winmm.dll; do
|
||||
[ -f "$GAMEDIR/$f" ] && rm -v "$GAMEDIR/$f"
|
||||
done
|
||||
fi
|
||||
remove_ini
|
||||
echo "[+] Done. No game file was ever modified."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- install ------------------------------------------------------------------
|
||||
ASI="$HERE/vendor/SUWSF-x64/SUWSF.asi"
|
||||
LOADER_SRC="$HERE/vendor/SUWSF-x64/dsound.dll" # Ultimate ASI Loader (adapts by filename)
|
||||
INI="$GAMES_DIR/$GAME/SUWSF.ini"
|
||||
for f in "$ASI" "$LOADER_SRC" "$INI"; do
|
||||
[ -f "$f" ] || { echo "[!] missing $f"; exit 1; }
|
||||
done
|
||||
if [ "$METHOD" = "bepinex" ]; then
|
||||
BEPZIP=$(ls "$HERE"/vendor/BepInEx_win_x64_*.zip 2>/dev/null | head -1)
|
||||
PLUGIN="$GAMES_DIR/$GAME/$PLUGIN_DLL"
|
||||
[ -f "$BEPZIP" ] || { echo "[!] missing BepInEx zip in vendor/"; exit 1; }
|
||||
[ -f "$PLUGIN" ] || { echo "[!] missing prebuilt plugin: $PLUGIN"; exit 1; }
|
||||
|
||||
cp -v "$ASI" "$GAMEDIR/SUWSF.asi"
|
||||
cp -v "$INI" "$GAMEDIR/SUWSF.ini"
|
||||
cp -v "$LOADER_SRC" "$GAMEDIR/$LOADER"
|
||||
if [ -f "$GAMEDIR/winhttp.dll" ]; then
|
||||
echo "[i] BepInEx already present; updating plugin only."
|
||||
else
|
||||
command -v unzip >/dev/null || { echo "[!] unzip required"; exit 1; }
|
||||
unzip -o -q "$BEPZIP" -d "$GAMEDIR"
|
||||
echo "[+] Installed BepInEx ($(basename "$BEPZIP"))"
|
||||
fi
|
||||
mkdir -p "$GAMEDIR/BepInEx/plugins"
|
||||
cp -v "$PLUGIN" "$GAMEDIR/BepInEx/plugins/"
|
||||
else
|
||||
ASI="$HERE/vendor/SUWSF-x64/SUWSF.asi"
|
||||
LOADER_SRC="$HERE/vendor/SUWSF-x64/dsound.dll" # Ultimate ASI Loader (adapts by filename)
|
||||
INI="$GAMES_DIR/$GAME/SUWSF.ini"
|
||||
for f in "$ASI" "$LOADER_SRC" "$INI"; do
|
||||
[ -f "$f" ] || { echo "[!] missing $f"; exit 1; }
|
||||
done
|
||||
|
||||
cp -v "$ASI" "$GAMEDIR/SUWSF.asi"
|
||||
cp -v "$INI" "$GAMEDIR/SUWSF.ini"
|
||||
cp -v "$LOADER_SRC" "$GAMEDIR/$LOADER"
|
||||
fi
|
||||
apply_ini
|
||||
|
||||
cat <<EOF
|
||||
|
||||
[+] Installed: SUWSF.asi, SUWSF.ini, $LOADER
|
||||
[+] Installed ($METHOD): $([ "$METHOD" = "bepinex" ] && echo "BepInEx + $PLUGIN_DLL + $LOADER" || echo "SUWSF.asi, SUWSF.ini, $LOADER")
|
||||
|
||||
NEXT (Proton) — REQUIRED, or the loader is ignored and the fix won't apply in gameplay.
|
||||
Steam > right-click ${TITLE:-$GAME} > Properties > Launch Options:
|
||||
@@ -138,6 +164,12 @@ NEXT (Proton) — REQUIRED, or the loader is ignored and the fix won't apply in
|
||||
|
||||
Then set the in-game resolution to your native ultrawide res, fullscreen.
|
||||
|
||||
Tuning (METHOD=bepinex games):
|
||||
Config is generated on first launch at
|
||||
<game>/BepInEx/config/*.cfg (edits apply live, ~2s, no restart)
|
||||
Plugin log (proves whether it applied):
|
||||
<game>/BepInEx/LogOutput.log
|
||||
|
||||
Troubleshooting:
|
||||
Different loader name: LOADER_NAME=version.dll ./install.sh $GAME
|
||||
Diagnose injection: add PROTON_LOG=1 to launch options, then
|
||||
|
||||
Reference in New Issue
Block a user