Skip to content

Instantly share code, notes, and snippets.

@Benjamin-Wegener
Last active May 5, 2026 06:35
Show Gist options
  • Select an option

  • Save Benjamin-Wegener/2289ee830a1b0195d4fb86d47833d6d6 to your computer and use it in GitHub Desktop.

Select an option

Save Benjamin-Wegener/2289ee830a1b0195d4fb86d47833d6d6 to your computer and use it in GitHub Desktop.
Hogwarts Legacy – Heroic Launcher fix script (Mac M4)
#!/usr/bin/env bash
# Hogwarts Legacy – Heroic Launcher fix script v3 (Mac M4)
LOG="$HOME/hogwarts_fix_$(date +%Y%m%d_%H%M%S).log"
exec > >(tee -a "$LOG") 2>&1
ok() { echo " [OK] $*"; }
warn() { echo " [!!] $*"; }
info() { echo " --> $*"; }
section() { echo; echo "=== $* ==="; } # renamed: was head(), clashed with /usr/bin/head
echo "Hogwarts Legacy fix script v3"
echo "Log: $LOG"
GAME_DIR="/Users/user/Games/Heroic"
HEROIC_CFG="$HOME/Library/Application Support/heroic"
# ── 1. Locate Wine prefix ────────────────────────────────────
section "1. Locating Wine prefix"
PREFIX=""
SEARCH_DIRS=()
[[ -d "$HEROIC_CFG" ]] && SEARCH_DIRS+=("$HEROIC_CFG")
[[ -d "$GAME_DIR" ]] && SEARCH_DIRS+=("$GAME_DIR")
[[ -d "$HOME/Games" ]] && SEARCH_DIRS+=("$HOME/Games")
info "Searching in: ${SEARCH_DIRS[*]}"
if [[ ${#SEARCH_DIRS[@]} -gt 0 ]]; then
while IFS= read -r dc; do
[[ -z "$dc" ]] && continue
CANDIDATE=$(dirname "$dc")
info "Found drive_c at: $CANDIDATE"
if echo "$CANDIDATE" | grep -qi "hogwart\|legacy"; then
PREFIX="$CANDIDATE"
break
fi
[[ -z "$PREFIX" ]] && PREFIX="$CANDIDATE"
done < <(find "${SEARCH_DIRS[@]}" -maxdepth 6 -name "drive_c" -type d 2>/dev/null)
fi
for FIXED in \
"$HEROIC_CFG/wineprefix/HogwartsLegacy" \
"$HEROIC_CFG/prefixes/HogwartsLegacy" \
"$HEROIC_CFG/wineprefix/default" \
"$HOME/my-game-prefix" \
"$GAME_DIR/Hogwarts Legacy/wine" \
"$GAME_DIR/HogwartsLegacy/wine"; do
if [[ -d "$FIXED/drive_c" && -z "$PREFIX" ]]; then
PREFIX="$FIXED"
info "Matched fixed path: $PREFIX"
fi
done
if [[ -z "$PREFIX" ]]; then
warn "No Wine prefix found. Dumping dirs for manual inspection:"
echo "--- heroic config ---"
ls -la "$HEROIC_CFG/" 2>/dev/null || echo "(not found)"
echo "--- game dir ---"
ls -la "$GAME_DIR/" 2>/dev/null || echo "(not found)"
echo "--- find drive_c (10s timeout) ---"
timeout 10 find ~ -name "drive_c" -type d 2>/dev/null || true
warn "Re-run with: PREFIX=\"/path/to/prefix\" bash fix_hogwarts.sh"
exit 0
fi
ok "Using prefix: $PREFIX"
DRIVE_C="$PREFIX/drive_c"
# ── 2. Delete ProgramData relaunch blocker ───────────────────
section "2. ProgramData relaunch blocker"
PD="$DRIVE_C/ProgramData/Hogwarts Legacy"
if [[ -d "$PD" ]]; then
info "Found: $PD"
ls -lh "$PD" 2>/dev/null | sed 's/^/ /' || true
rm -rf "$PD"
ok "Deleted ProgramData/Hogwarts Legacy"
else
ok "Not present (already clean)"
fi
# ── 3. Patch MSync / ESync ───────────────────────────────────
section "3. MSync / ESync settings"
SETTINGS_FILE=""
while IFS= read -r f; do
[[ -z "$f" ]] && continue
if grep -qi "hogwart\|HogwartsLegacy" "$f" 2>/dev/null; then
SETTINGS_FILE="$f"
break
fi
done < <(find "$HEROIC_CFG" -name "*.json" -maxdepth 5 2>/dev/null)
if [[ -z "$SETTINGS_FILE" ]]; then
warn "No settings JSON found for Hogwarts Legacy"
warn "Manual fix: Heroic -> game -> Settings -> Wine -> disable MSync + ESync"
else
ok "Settings file: $SETTINGS_FILE"
cp "$SETTINGS_FILE" "${SETTINGS_FILE}.bak" 2>/dev/null && info "Backup: ${SETTINGS_FILE}.bak"
python3 - "$SETTINGS_FILE" <<'PYEOF'
import json, sys
path = sys.argv[1]
try:
with open(path) as f:
d = json.load(f)
changed = []
for key in ('enableMsync', 'enableEsync'):
old = d.get(key, 'NOT SET')
print(f" {key}: {old}", end="")
if old is not False:
d[key] = False
changed.append(key)
print(" --> false (patched)")
else:
print(" (already false)")
if changed:
with open(path, 'w') as f:
json.dump(d, f, indent=2)
print(" [OK] Saved changes")
else:
print(" [OK] No changes needed")
except Exception as e:
print(f" [!!] Could not patch: {e}")
PYEOF
fi
# ── 4. vcrun2022 check ───────────────────────────────────────
section "4. vcrun2022 / Visual C++ runtime"
VC_OK=true
for dll in msvcp140.dll vcruntime140.dll vcruntime140_1.dll; do
f="$DRIVE_C/windows/system32/$dll"
if [[ -f "$f" ]]; then
ok "$dll present ($(du -sh "$f" | cut -f1))"
else
warn "$dll MISSING"
VC_OK=false
fi
done
if [[ "$VC_OK" == false ]]; then
echo " ACTION: Heroic -> game -> Settings -> WineTricks -> install vcrun2022"
fi
# ── 5. Game executable ───────────────────────────────────────
section "5. Game executable"
EXE=$(find "$GAME_DIR" -name "HogwartsLegacy.exe" 2>/dev/null | grep -v "^\s*$" | /usr/bin/head -n 1)
if [[ -n "$EXE" ]]; then
ok "Found: $EXE"
info "Size: $(du -sh "$EXE" 2>/dev/null | cut -f1)"
else
warn "HogwartsLegacy.exe not found under $GAME_DIR"
info "Searching home dir..."
find ~ -name "HogwartsLegacy.exe" 2>/dev/null | /usr/bin/head -n 3 || true
fi
# ── 6. Recent Heroic error logs ─────────────────────────────
section "6. Recent Heroic error logs"
HEROIC_LOG=""
for LOGDIR in \
"$HOME/Library/Logs/Heroic" \
"$HOME/Library/Application Support/heroic/logs"; do
if [[ -d "$LOGDIR" ]]; then
MAYBE=$(find "$LOGDIR" -name "*.log" 2>/dev/null | sort -r | /usr/bin/head -n 1)
if [[ -n "$MAYBE" ]]; then
HEROIC_LOG="$MAYBE"
break
fi
fi
done
if [[ -n "$HEROIC_LOG" ]]; then
ok "Log: $HEROIC_LOG"
echo
grep -iE "(error|uproject|fail|crash|warn|hogwart)" "$HEROIC_LOG" 2>/dev/null \
| /usr/bin/tail -n 30 | sed 's/^/ /' || echo " (no matching lines)"
else
warn "No Heroic log file found"
fi
# ── Done ────────────────────────────────────────────────────
section "Done"
echo "Full output saved to: $LOG"
echo
echo "Next steps:"
echo " 1. Launch Hogwarts Legacy from Heroic"
echo " 2. If shaders fail on first launch, close and relaunch once"
echo " 3. If still broken, share: $LOG"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment