Skip to content

Instantly share code, notes, and snippets.

@und3fined
Last active July 4, 2026 13:57
Show Gist options
  • Select an option

  • Save und3fined/9bb724cfd3d5a486eaef30991c193b15 to your computer and use it in GitHub Desktop.

Select an option

Save und3fined/9bb724cfd3d5a486eaef30991c193b15 to your computer and use it in GitHub Desktop.
Fix crash `王者荣耀世界` (`Honor of Kings: World`) on PlayCover
#!/bin/sh
#
# patch_ngr.sh — PlayCover NGR (com.tencent.ngr) path-prefix fix
#
# NOTE: PlayCover reverts this whenever it re-imports/updates the app. Re-run the
# script after any re-import, or bake the same patch into the .ipa before importing.
#
# How to get the script:
# - Download script from `https://gist.github.com/und3fined/9bb724cfd3d5a486eaef30991c193b15`
# - Or curl -L https://gist.githubusercontent.com/und3fined/9bb724cfd3d5a486eaef30991c193b15/raw/patch_ngr.sh -o patch_ngr.sh
# - Chmod the script: `chmod +x patch_ngr.sh`
#
# Usage:
# ./patch_ngr.sh # patch the installed PlayCover app
# ./patch_ngr.sh /path/to/NGR # patch a specific Mach-O executable
#
set -eu
DEFAULT_BUNDLE="$HOME/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.ngr.app"
# --- resolve the executable ---------------------------------------------------
if [ "$#" -ge 1 ]; then
EXE="$1"
else
if [ ! -d "$DEFAULT_BUNDLE" ]; then
echo "error: app bundle not found: $DEFAULT_BUNDLE" >&2
echo " pass the executable path explicitly: $0 /path/to/NGR" >&2
exit 1
fi
EXE="$DEFAULT_BUNDLE/$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$DEFAULT_BUNDLE/Info.plist")"
fi
[ -f "$EXE" ] || { echo "error: executable not found: $EXE" >&2; exit 1; }
echo "target: $EXE"
# UTF-16LE byte patterns
FIND='\x2F\x00\x76\x00\x61\x00\x72\x00\x2F\x00\x00\x00'
REPL='\x2F\x00\x55\x00\x73\x00\x65\x00\x72\x00\x00\x00'
count() { perl -e 'local $/; my $d=<STDIN>; my $p=shift; my $c=()=($d=~/$p/g); print $c' "$1" < "$EXE"; }
NFIND=$(count "$FIND")
NREPL=$(count "$REPL")
# --- idempotency: already patched? -------------------------------------------
if [ "$NFIND" = "0" ] && [ "$NREPL" -ge "1" ]; then
echo "already patched. nothing to do."
exit 0
fi
# --- safety guard: exactly one target ----------------------------------------
if [ "$NFIND" != "1" ]; then
echo "error: expected exactly one bare, found $NFIND — aborting." >&2
echo " (binary layout may have changed; inspect before patching.)" >&2
exit 1
fi
# --- backup -------------------------------------------------------------------
BK="$EXE.orig-$(date +%Y%m%d-%H%M%S)"
cp -p "$EXE" "$BK"
echo "backup: $BK"
# --- patch in place (equal length, no offset shift) --------------------------
perl -e '
open F, "+<:raw", $ARGV[0] or die "$ARGV[0]: $!";
local $/; my $d = <F>;
my $i = index($d, "\x2F\x00\x76\x00\x61\x00\x72\x00\x2F\x00\x00\x00");
die "pattern vanished\n" if $i < 0;
seek F, $i, 0;
print F "\x2F\x00\x55\x00\x73\x00\x65\x00\x72\x00\x00\x00";
close F;
' "$EXE"
# --- verify bytes -------------------------------------------------------------
if [ "$(count "$FIND")" != "0" ] || [ "$(count "$REPL")" -lt "1" ]; then
echo "error: post-patch verification failed; restoring backup." >&2
cp -p "$BK" "$EXE"
exit 1
fi
echo "Patched successfully!"
# --- re-sign ad-hoc (PlayCover disables library validation) ------------------
codesign -f -s - --preserve-metadata=entitlements,flags "$EXE"
codesign -v "$EXE" && echo "codesign: valid"
echo "Done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment