Last active
July 4, 2026 13:57
-
-
Save und3fined/9bb724cfd3d5a486eaef30991c193b15 to your computer and use it in GitHub Desktop.
Fix crash `王者荣耀世界` (`Honor of Kings: World`) on PlayCover
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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