Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🎮 Mac Mobile Gaming Tutorials

欢迎来到本网站!
这里专注于整理与分析在 macOS 上运行手机游戏的常见问题及对应解决方案。

网站内容

  • 新游概况:近期上线新游的运行情况测试结果。

  • 游戏列表:针对特定游戏的问题分析与解决方法。

  • 教程列表:Mac玩手游相关的通用教程内容。

常用工具

图标工具说明
PlayCover可安装iOS游戏,原生运行无损耗。支持分辨率调整、按键映射等功能。
PlayCover NightlyPlayCover的早期测试版本,包含新的功能、新的修复以及对最新macOS的适配。
Sideloadly可安装iOS游戏,原生运行无损耗。使用免费证书签名时,每7天需要重新安装一次。
CrossOver可安装Windows游戏。
支持 最新Wine + D3DMetal / DXMT
CrossOver PreviewCrossOver的预览测试版本,包含新的功能、新的修复以及最新版本的Wine。
Sikarugir可安装Windows游戏。
支持 旧版Wine + D3DMetal / DXMT
盖世游戏 Mac版可安装Windows游戏。
支持 最新Wine + D3DMetal / DXMT
应用宝 Mac版同时包含 安卓模拟器 和 Wine转译工具。
BlueStacks Air安卓模拟器。
MuMu模拟器 Pro安卓模拟器。收费。

IPA资源站点

图标站点说明
https://decrypt.day可免费下载IPA。
免费链接可能会在下载一定次数后失效,建议在游戏版本更新当天尽快下载。
https://armconverter.com可免费下载美区IPA,其他区收费。
https://ipa.store可免费下载国区和美区IPA,使用国内网盘。

新游概况

游戏名上线时间引擎App StorePlayCover
Sideloadly
CrossOver
Wine
备注
怪物猎人:旅人 26/10/29UE5✅
绿梦:时空之声 26/10/15Unity✅
伊莫26/09/23Unity✅✅
闪耀吧!噜咪26/09/17Unity✅✅
王者万象棋26/09/10Unity✅❌
诡秘之主 26/08/21UE5✅❌
燕云十六声Mac版26/08/17Messiah✅ 官网下载
幻想水浒传 STAR LEAP26/08/07Unity✅
魂坠深境26/08/06Unity✅✅
龙之谷:启程26/07/29Unity✅✅
无职转生 回响编年史
(#無職転生…)(#無職転生 ~異世界行ったら本気だす~ クロニクル・オブ・エコーズ)
26/07/27Unity✅✅
飙速宅男 共鸣踏板
(弱虫ペダル…)(弱虫ペダル レゾナンス・ペダイズム)
26/07/24Unity✅
遗忘之海26/07/23Messiah✅✅
hololive Dreams26/07/23Unity✅❌
玛奇 Mobile
(台服)
26/07/22Unity✅❌❌
数码宝贝 UP26/07/15Unity✅
失控进化 26/07/09Unity✅❌
时空猎人·觉醒26/07/02Unity✅✅
舞力全开:派对26/07/02Unity✅
Star Sailors26/06/30Unity✅❌
赛马娘PC版
(台服)
26/06/27Unity✅
天堂2:盟约
(国服)
26/06/24UE4✅❌
雪松26/06/22Unity✅✅
宝可梦冠军26/06/17Unity❌
像素深渊
(ドットアビス)
26/06/11Unity✅✅
苍蓝前线26/06/10Unity✅
月相计划26/06/09Unity✅✅
闪电十一人 Cross26/06/09Unity✅
夜幕之下26/06/05Unity✅✅✅
卡厄思梦境
(国服)
26/05/28YUNA✅❌
权力的游戏:国王大道26/05/21UE5✅✅✅
镭明闪击
(国服)
26/05/15Unity✅❌gpHackerProc.dll
大航海时代:起源
(国服)
26/04/28UE4✅❌
乱涂!彩世界26/04/28Unity✅✅
无限暖暖Mac版26/04/24UE5✅
异环 26/04/23UE5✅✅
三国:百将牌26/04/22Unity✅✅✅
勇者斗恶龙 破限乱斗26/04/21Unity❌
王者荣耀世界 26/04/17UE4✅❌
魔御:STAR DIVE 26/04/15UE5✅✅
猫娘乐园 世界连结26/04/14Unity❌
亿万光年26/04/08Unity✅✅
幻想少女公会26/04/02Unity✅✅
全境封锁:曙光26/03/31UE4✅
洛克王国:世界 26/03/26UE4✅❌
DISSIDIA DUELLUM
FINAL FANTASY
26/03/24Unity✅
七大罪:Origin 26/03/24UE5✅❌
Star Savior
(国际服)
26/03/19Unity✅✅✅
约会大作战:
Love Limit Break
26/03/17Unity✅
三国志异闻录26/03/17Unity✅
VAMPIR:血之继承者26/03/11UE5✅✅
我推的孩子
Puzzle Star
26/02/25Unity✅
彩虹六号M26/02/24Unity❌
テクロノス26/02/19Unity✅
HUNTER×HUNTER
NEN×SURVIVOR
26/02/18Unity❌
魔法少女小圆
Magia Exedra
(台服)
26/02/10Unity❌✅
吉星派对26/02/06Unity✅✅✅
天界地狱
(헤븐헬즈)
26/02/04Unity✅✅
少女前线:火力控制
(东南亚服)
26/01/29Unity✅
汉克旅店26/01/28Unity✅
明日方舟:终末地 26/01/22Unity✅✅
龙之剑
(드래곤소드)
26/01/21UE5❌❌
蔚蓝档案PC版
(日服) 14
26/01/20Unity✅
空灵诗篇
(国服)
26/01/15Unity✅✅
逆战:未来 26/01/13UE4✅❌
疯狂水世界26/01/08Unity✅✅
风之痕迹26/01/08Unity❌✅✅

游戏列表

碧蓝航线

PlayCover

1. 按键映射失灵 ISSUE-014

同时按下WASD和鼠标后,按键映射失灵,重启游戏后恢复正常。

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.bilibili.azurlane.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/SessionProvider/{found=1} found && /init/{f=1} f && /imp/{print $2; exit}')
printf '\x1F\x20\x03\xD5' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x1C4)) conv=notrunc
printf '\x1F\x20\x03\xD5' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x374)) conv=notrunc
codesign -fs- $EXECUTABLE

边狱巴士

PlayCover

1. 启动闪退 ISSUE-010

右键游戏图标 - 设置 - 绕过设置,启用“绕过越狱检测”选项。

2. 屏幕方向错误 ISSUE-013

按command+R可以旋转屏幕方向,或通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.ProjectMoon.LimbusCompany.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/UnityAppController/{found=1} found && /createRootViewController$/{f=1} f && /imp/{print $2; exit}')
printf '\x1F\x20\x03\xD5' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x28)) conv=notrunc
printf '\x82\x00\x80\xD2' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x34)) conv=notrunc
codesign -fs- $EXECUTABLE

3. 自动登录闪退 ISSUE-005

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.ProjectMoon.LimbusCompany.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/FIRAuthKeychainServices/{found=1} found && /itemWithQuery:error:/{f=1} f && /imp/{print $2; exit}')
printf '\x44\x00\x00\x14' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x110)) conv=notrunc
printf '\x1F\x20\x03\xD5' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x2A4)) conv=notrunc
codesign -fs- $EXECUTABLE

4. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

CrossOver

正常运行。

蛋仔派对

PlayCover

1. 启动闪退 ISSUE-018

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netease.party.app/client
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x2F\x70\x72\x69\x76\x61\x74\x65\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x00\x2F\x00\x00\x00\x00\x00\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

第五人格

PlayCover

1. 启动闪退 ISSUE-018

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netease.id5.app/client
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x2F\x70\x72\x69\x76\x61\x74\x65\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x00\x2F\x00\x00\x00\x00\x00\x00\x00\x00"; my $i = index($d, "\xF4\x05\x8E\xD2\x54\x2E\xAD\xF2\xD4\x2E\xCC\xF2\x94\xAE\xEC\xF2"); exit 2 if $i < 0; seek F, $i + 48, 0; print F "\x08\x00\x80\xD2"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

CrossOver

1. 发烧游戏下载按钮没反应 ISSUE-026

通过终端指令修复:

sudo sysctl net.inet.tcp.sendspace=1048576

下载完成还原操作:

sudo sysctl net.inet.tcp.sendspace=131072

地下城与勇士:起源

PlayCover

1. 启动闪退 ISSUE-024

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.cdnf.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/KeyboardDelegate/{found=1} found && /Initialize/{f=1} f && /imp/{print $2; exit}')
printf '\x1F\x20\x03\xD5' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x84)) conv=notrunc
codesign -fs- $EXECUTABLE

巅峰极速

PlayCover

1. 启动阶段异常卡顿 ISSUE-001

下载完最开始的200MB资源后,通过终端指令修复:

BUNDLE_ID=com.netease.rc
rm -r /Users/$USER/Library/Containers/$BUNDLE_ID/Data/Library/Users/$USER/Documents/Containers/$BUNDLE_ID/Data && ln -sf /Users/$USER/Library/Containers/$BUNDLE_ID/Data /Users/$USER/Library/Containers/$BUNDLE_ID/Data/Library/Users/$USER/Documents/Containers/$BUNDLE_ID/Data
rm -r /Users/$USER/Library/Containers/$BUNDLE_ID/Data/Library/Users/$USER/Library/Containers/$BUNDLE_ID/Data && ln -sf /Users/$USER/Library/Containers/$BUNDLE_ID/Data /Users/$USER/Library/Containers/$BUNDLE_ID/Data/Library/Users/$USER/Library/Containers/$BUNDLE_ID/Data

2. 提示“设备不支持更高画质” ISSUE-011

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netease.rc.app/g112
FUNC_ADDR=$(otool -Iv "$EXECUTABLE" | grep _os_proc_available_memory | head -n1 | awk '{print $1}')
printf '\x20\x00\xC0\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

二重螺旋

PlayCover

1. 存储空间不足报错 ISSUE-001

通过终端指令修复:

rm -r /Users/$USER/Library/Containers/com.hero.dna.ios/Data/Library/Users/$USER/Library/Containers/com.hero.dna.ios/Data && ln -sf /Users/$USER/Library/Containers/com.hero.dna.ios/Data /Users/$USER/Library/Containers/com.hero.dna.ios/Data/Library/Users/$USER/Library/Containers/com.hero.dna.ios/Data

2. 鼠标点击UI无反应 ISSUE-003

使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

3. 解锁60帧

右键游戏图标,选择“显示应用数据”,进入二重螺旋/Data/Library/EM/Saved/Config/IOS,用文本编辑打开Engine.ini,在文件末尾添加:

[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
FrameRateLock=PUFRL_60

4. 客服界面屏幕方向错误 ISSUE-019

通过终端指令修复:

国服

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.hero.dna.ios.app/Frameworks/Game.framework/Game
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/HMServiceViewController/{found=1} found && /supportedInterfaceOrientations/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x03\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

国际服

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.panstudio.duetnightabyss.arpg.global.app/Frameworks/HeroGlobalSDK.framework/HeroGlobalSDK
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/HGKFVC/{found=1} found && /supportedInterfaceOrientations/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x03\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

5. 运行帧率低/发热严重

右键游戏图标,选择“显示应用数据”,进入二重螺旋/Data/Library/EM/Saved/Config/IOS,用文本编辑打开DeviceProfiles.ini,在文件末尾添加:

[IPadPro DeviceProfile]
CVars=r.MobileContentScaleFactor=1.0

可任意修改等号后面的数值。数值越小,画面越糊,运行越流畅,发热越少。

6. 剧情过场演出卡死

原因不明。可以尝试以下方法:

  • 画质设置 - 显示 - 特效细节改为“低”或“极低”
  • 快速点击跳过按钮
  • 用云游戏过掉这段剧情

CrossOver

因反作弊无法运行。

怪物猎人:旅人

PlayCover

1. 启动报错“Game files … missing” ISSUE-001

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.mhadv.app/MHMobile-IOS-Shipping
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x2F\x00\x76\x00\x61\x00\x72\x00\x2F\x00\x00\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x2F\x00\x55\x00\x73\x00\x65\x00\x72\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

2. 运行一分钟后闪退 ISSUE-012

右键游戏图标 - 设置 - 绕过设置,启用“blockSleepSpamming”选项。

诡秘之主

PlayCover

1. 启动闪退 ISSUE-028

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.gmzz.tzyz.ios.app/C7
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x28\x02\x80\x52\xE0\x03\x08\xAA\x88\x00\x80\x52\xE1\x03\x08\xAA\x02\x00\x80\xD2"); exit 1 if $i < 0; seek F, $i + 0x14, 0; print F "\x00\x00\x80\xD2"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

2. 运行一分钟后闪退 ISSUE-012

使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“blockSleepSpamming”选项。

3. 鼠标点击UI无反应 ISSUE-003

使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

4. 下载速度极慢 ISSUE-011

原因未知,猜测是因为游戏检测不到实际的可用运行内存。

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.gmzz.tzyz.ios.app/C7
FUNC_ADDR=$(otool -Iv "$EXECUTABLE" | grep _os_proc_available_memory | head -n1 | awk '{print $1}')
printf '\x20\x00\xC0\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

5. 每次打开都会编译着色器

解决方法:点击查看视频。

6. 攻略界面显示异常

通过浏览器访问:https://lom.sparknexa.com/wiki

7. 运行帧率低/发热严重

尝试降低分辨率缩放比例:

右键游戏图标 - 在访达中查看 - 右键游戏文件 - 查看包内容,用文本编辑打开uecommandline.txt,在末尾添加mcsf参数(MobileContentScaleFactor)。

-project="../../../C7/C7.uproject" mcsf=1.0

8. 解锁60帧补丁

通过终端指令写入补丁:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.gmzz.tzyz.ios.app/C7
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x08\x1C\x08\x72\x09\x40\xA0\x52"); exit 1 if $i < 0; seek F, $i - 28, 0; print F "\xCA\x09\xE8\xD2"; seek F, $i + 40, 0; print F "\x40\x01\x67\x9E"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

CrossOver

因反作弊无法运行。

幻塔

App Store

Mac原生版本,正常运行。

PlayCover

1. 游戏跳过更新资源直接到达登录界面 ISSUE-001

通过终端指令修复:

rm -r /Users/$USER/Library/Containers/com.pwrd.huanta/Data/Documents/Users/$USER/Library/Containers/com.pwrd.huanta/Data && ln -sf /Users/$USER/Library/Containers/com.pwrd.huanta/Data /Users/$USER/Library/Containers/com.pwrd.huanta/Data/Documents/Users/$USER/Library/Containers/com.pwrd.huanta/Data

2. 角色贴图模糊 ISSUE-011

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.pwrd.huanta.app/QRSL
FUNC_ADDR=$(otool -Iv "$EXECUTABLE" | grep _os_proc_available_memory | head -n1 | awk '{print $1}')
printf '\x20\x00\xC0\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

修复前后的对比:

火炬之光:无限

PlayCover

1. 启动闪退 ISSUE-001

通过终端指令修复:

rm -r /Users/$USER/Library/Containers/com.xindong.torchlight/Data/Library/Users/$USER/Library/Containers/com.xindong.torchlight/Data && ln -sf /Users/$USER/Library/Containers/com.xindong.torchlight/Data /Users/$USER/Library/Containers/com.xindong.torchlight/Data/Library/Users/$USER/Library/Containers/com.xindong.torchlight/Data

2. 鼠标点击UI无反应 ISSUE-003

使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

金铲铲之战

PlayCover

1. 麦克风权限问题

游戏提示“您拒绝了麦克风权限,请在MacOS系统设置,隐私和安全设置当中手动打开金铲铲之战麦克风权限”。

原因分析

游戏通过UnityEngine.Application.HasUserAuthorization(UserAuthorization.Microphone)查询麦克风权限,但是由于游戏没有声明宏定义UNITY_USES_MICROPHONE,从而导致游戏打包时并没有包含麦克风权限的相应代码,所以HasUserAuthorization()总是返回false。

写入补丁,强制HasUserAuthorization()返回true可暂时解决。


通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.jkchess.app/jkchess
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x7F\x0A\x00\x71\x93\x02\x88\x1A\xE0\x03\x13\xAA"); exit 1 if $i < 0; seek F, $i + 8, 0; print F "\x20\x00\x80\xD2"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

2. 麦克风权限问题2 ISSUE-016

游戏提示“没有麦克风权限,请先开启麦克风权限哦~“。

解决方法:使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“checkMicPermissionSync”选项。

Warning

如果同时通过Sideloadly和PlayCover安装了游戏,麦克风的授权记录可能会出现错乱的情况。

两边都卸载干净,再通过PlayCover重新安装一次即可解决问题。


3. 阵容推荐显示问题 ISSUE-019

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.jkchess.app/Frameworks/MSDKPIXWebView.framework/MSDKPIXWebView
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/MSDKPIXWKWebViewController/{found=1} found && /supportedInterfaceOrientations/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x03\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

4. 阵容推荐打不了字 ISSUE-017

临时解决办法:右键游戏图标 - 设置 - 键盘映射设置,禁用“智能按键映射”。

绝区零

PlayCover

1. 画面未铺满窗口

原因分析:
3.3版本后,游戏官方将 Info.plist 中的UIRequiresFullScreen调整为false,我们只需要把它改回true即可解决画面显示问题。

修复步骤:
执行以下终端指令,关闭PlayCover重新打开,然后从PlayCover界面启动一次游戏。

/usr/libexec/PlistBuddy -c "Set :UIRequiresFullScreen true" ~/Library/Containers/io.playcover.PlayCover/Applications/com.miHoYo.Nap.app/Info.plist

开放空间

App Store

iOS版本,正常运行但存在一些问题。

PlayCover

1. 闪退问题 ISSUE-020

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.Nekootan.kfkj.apple.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/o0_ooo0o0/{found=1} found && /o0_oaoao0/{f=1} f && /imp/{print $2; exit}')
printf '\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

2. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

CrossOver

1. 更新界面不显示文字

点CrossOver界面左下角的“安装”,搜索“思源黑体”。

2. 登录界面加载不出来 ISSUE-021

点CrossOver界面右上角的“运行命令”,执行以下命令:

reg add "HKCU\Environment" /v QT_QUICK_BACKEND /t REG_SZ /d "software" /f

洛克王国:世界

PlayCover

1. 安装时闪退

PlayCover Nightly版 (1437) 已修复此问题。

2. 运行一分钟后闪退 ISSUE-012

右键游戏图标 - 设置 - 绕过设置,启用“blockSleepSpamming”选项。

3. 初始化失败报错 ISSUE-001

通过终端指令修复:

rm -rf /Users/$USER/Library/Containers/com.tencent.nrc/Data/Documents/Users/$USER/Library/Containers/com.tencent.nrc/Data && ln -sf /Users/$USER/Library/Containers/com.tencent.nrc/Data /Users/$USER/Library/Containers/com.tencent.nrc/Data/Documents/Users/$USER/Library/Containers/com.tencent.nrc/Data

4. 鼠标点击UI没反应 ISSUE-003

右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

5. 麦克风问题 ISSUE-016

右键游戏图标 - 设置 - 绕过设置,启用“checkMicPermissionSync”选项。

6. 咕噜球瞄准模式

6.1 进入映射编辑模式。

6.2 添加一个Mouse映射。

6.3 选中Mouse映射,再按下键盘上的某个键(以E键为例)。

6.4 退出映射编辑模式。

6.5 按住E键的同时,挪动鼠标进行瞄准。

CrossOver

因反作弊无法运行。

绿梦:时空之声

PlayCover

1. 闪退问题 ISSUE-020

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.zhuziplay.lvmengnew.op.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/o0_ooo0o0/{found=1} found && /o0_oaoao0/{f=1} f && /imp/{print $2; exit}')
printf '\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

锚点降临

App Store

iOS版本,加载卡住无法游玩。

PlayCover

1. 加载卡住问题 ISSUE-022

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.leiyan.mdjl.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/InlandSDKManager/{found=1} found && /_reqATTracking:/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x00\x80\xD2' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x38)) conv=notrunc
codesign -fs- $EXECUTABLE

2. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

鸣潮

App Store

Mac原生版本,正常运行。

PlayCover

1. 中文系统下启动闪退 ISSUE-002

PlayCover Nightly版已修复此问题。

2. 检查应用更新时闪退 ISSUE-001

通过终端指令修复:

rm -r /Users/$USER/Library/Containers/com.kurogame.mingchao/Data/Library/Users/$USER/Library/Containers/com.kurogame.mingchao/Data && ln -sf /Users/$USER/Library/Containers/com.kurogame.mingchao/Data /Users/$USER/Library/Containers/com.kurogame.mingchao/Data/Library/Users/$USER/Library/Containers/com.kurogame.mingchao/Data

3. 国际服卡在应用补丁资源 ISSUE-029

解决方法一:打开活动监视器,杀掉 FamilyOutOfProcessUIExtension 进程。

解决方法二:通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.kurogame.wutheringwaves.global.app/Frameworks/KROverseaSDK.framework/KROverseaSDK
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/KRDeclaredAgeRangeService/{found=1} found && /isAgeRangeRequestAvailable/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x00\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

4. 登录界面点击时自动关闭 ISSUE-003

解决方法一:尝试通过触控板去点击。

解决方法二:尝试通过按键映射去点击。

解决方法三:使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

5. 更新界面点击下载按钮无反应 ISSUE-003

同第4点。

6. 键鼠如何使用快捷轮盘

点击查看教程

7. 打不了字 ISSUE-006

临时解决办法:右键游戏图标 - 设置 - 键盘映射设置,禁用“按键映射布局” 或 禁用“智能按键映射”。

8. 拉海洛地图卡顿/角色贴图模糊/进入无音区需加载 ISSUE-011

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.kurogame.mingchao.app/Client
FUNC_ADDR=$(otool -Iv "$EXECUTABLE" | grep _os_proc_available_memory | head -n1 | awk '{print $1}')
printf '\x20\x00\xC0\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

9. 运行帧率低/发热严重

尝试降低分辨率缩放比例:

右键游戏图标 - 在访达中查看 - 右键游戏文件 - 查看包内容,用文本编辑打开ue4commandline.txt,在末尾添加mcsf参数(MobileContentScaleFactor)。

../../../Client/Client.uproject mcsf=1.0

明日方舟:终末地

PlayCover

1. 运行一分钟后闪退 ISSUE-012

使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“blockSleepSpamming”选项。

2. 神秘弹窗

PlayCover Nightly版已进行屏蔽处理。

CrossOver

https://github.com/stoicswe/Endfield_FineWine

明日之后

PlayCover

1. 启动闪退 ISSUE-018

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netease.mrzh.app/g66
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x2F\x70\x72\x69\x76\x61\x74\x65\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x00\x2F\x00\x00\x00\x00\x00\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

魔法少女小圆Magia Exedra

Note

日服、国际服版本因反作弊无法运行,本页面仅讨论繁中服。

App Store

启动后无响应,无法游玩。

PlayCover

1. 启动后无响应 ISSUE-023

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/tw.sonet.magiaexedra.app/Frameworks/UnityFramework.framework/UnityFramework
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x00\xC0\x3D\x60\x02\x80\x3D\x00\x84\x40\xAD\x02\x8C\x41\xAD\x62\x8E\x01\xAD\x60\x86\x00\xAD\x00\x84\x42\xAD\x02\x1C\xC0\x3D"); exit 1 if $i < 0; seek F, $i - 4, 0; print F "\x1F\x00\x00\xB9"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE

2. 播放剧情动画提示“网络错误”

原因分析

游戏使用AVPro Video插件来播放网络视频流。

可能需要提供正确的keyServerToken才能播放,但在Mac环境下keyServerToken为空。

临时解决方法:使用其他设备观看。

3. 新帐号登录提示“网络错误”

临时解决方法:使用其他设备过完新手教程,再将帐号继承到Mac上。

4. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

5. 解锁高分辨率

通过终端指令写入补丁,解锁后会使用PlayCover图形设置的分辨率:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/tw.sonet.magiaexedra.app/Frameworks/UnityFramework.framework/UnityFramework
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x40\x20\x21\x1E\x4A\x4C\x21\x1E\x49\x19\x20\x1E"); exit 1 if $i < 0; seek F, $i + 4, 0; print F "\x4A\x5C\x21\x1E"; my $i = index($d, "\x20\x20\x22\x1E\x29\x4C\x22\x1E\x0A\x08\x29\x1E"); exit 2 if $i < 0; seek F, $i + 4, 0; print F "\x29\x5C\x22\x1E"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE

6. 解锁60帧补丁

通过终端指令写入补丁:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/tw.sonet.magiaexedra.app/Frameworks/UnityFramework.framework/UnityFramework
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x60\xFF\xFF\x35\xD5\x03\x80\x52\x34\x09\x00\xB4"); exit 1 if $i < 0; seek F, $i + 4, 0; print F "\x95\x07\x80\x52"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE

魔御:STAR DIVE

PlayCover

1. 触屏和键鼠UI反复切换

只能选择屏蔽游戏自带的键鼠支持,改用PlayCover的按键映射功能。

屏蔽自带键盘操作:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netmarble.monster2.app/BigCat
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x63\x4A\x08\x91\xE1\x03\x16\xAA\xE4\x03\x17\xAA"); exit 1 if $i < 0; seek F, $i + 0xD0, 0; print F "\x1F\x20\x03\xD5"; seek F, $i + 0x1A0, 0; print F "\x1F\x20\x03\xD5"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

屏蔽自带鼠标操作:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netmarble.monster2.app/BigCat
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x63\x4A\x08\x91\xE1\x03\x16\xAA\xE4\x03\x17\xAA"); exit 1 if $i < 0; seek F, $i + 0x60, 0; print F "\x1F\x20\x03\xD5"; seek F, $i + 0x15C, 0; print F "\x1F\x20\x03\xD5"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

2. 运行帧率低/发热严重

右键游戏图标,选择“显示应用数据”,进入STAR DIVE/Data/Documents/BigCat/Saved/Config/IOS,创建DeviceProfiles.ini,然后用文本编辑打开DeviceProfiles.ini:

[iPadPro5_129 DeviceProfile]
CVars=r.MobileContentScaleFactor=1.0

右键游戏图标 - 设置 - 图像设置,查看选定的iOS机型:

  • 如果是M1 iPad,则保持不变
  • 如果是M2 iPad,则将iPadPro5_129改为iPadPro6_129
  • 如果是M4 iPad,则将iPadPro5_129改为iPadPro7_129

可任意修改等号后面的数值。数值越小,画面越糊,运行越流畅,发热越少。

CrossOver

正常运行。

添加命令行参数--in-process-gpu可打开Netmarble Launcher。

逆战:未来

PlayCover

1. 用户协议界面闪退

右键游戏图标 - 设置 - 键盘映射设置,禁用“按键映射布局”。

过掉用户协议后再重新打开这个选项。

2. 下载资源无网络/卡在登录中/加载黑屏/加载闪退 ISSUE-001

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.tmgp.nz.app/NZMClient
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x2F\x00\x76\x00\x61\x00\x72\x00\x2F\x00\x00\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x2F\x00\x55\x00\x73\x00\x65\x00\x72\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

3. 摇杆映射问题 ISSUE-007

使用PlayCover Nightly版,在编辑模式中选中WASD控件,更改为自由摇杆模式。

4. 麦克风问题 ISSUE-016

使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“checkMicPermissionSync”选项。

5. 调整全局UI缩放

右键游戏图标,选择“显示应用数据”,进入逆战:未来/Data/Documents/NZM/Saved/Config/IOS,用文本编辑打开Engine.ini,在文件末尾添加:

[/Script/Engine.UserInterfaceSettings]
UIScaleRule=ShortestSide
UIScaleCurve=(EditorCurveData=(Keys=((Time=1440.000000,Value=0.70000000)),PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant,DefaultValue=0),ExternalCurve=None)

其中Time=1440表示分辨率高度1440,Value=0.7表示缩放值0.7,可随意修改。

CrossOver

因反作弊无法运行。

女神异闻录:夜幕魅影

PlayCover

1. 国服启动闪退 ISSUE-024

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“ignoreUnityKeyboardInitializationError”选项。

2. 国际服弹出错误报告 ISSUE-010

PlayCover Nightly版已修复此问题。

3. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

CrossOver

因反作弊无法运行。

七大罪:Origin

PlayCover

1. 中文系统下启动游戏闪退 ISSUE-002

PlayCover Nightly版已修复此问题。

2. 网络不稳定, 资源下载失败 ISSUE-001

通过终端指令修复:

rm -r /Users/$USER/Library/Containers/com.netmarble.nanaori/Data/Documents/Users/$USER/Library/Containers/com.netmarble.nanaori/Data && ln -sf /Users/$USER/Library/Containers/com.netmarble.nanaori/Data /Users/$USER/Library/Containers/com.netmarble.nanaori/Data/Documents/Users/$USER/Library/Containers/com.netmarble.nanaori/Data

3. 鼠标点击异常 ISSUE-003

鼠标点击时,屏幕左上角出现第二个点击特效。

使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

CrossOver

因反作弊无法运行。

七骑士 Re:BIRTH

PlayCover

1. 点击弹窗界面时会自动关闭 ISSUE-003

使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

CrossOver

正常运行,播放视频时会黑屏。

添加命令行参数--in-process-gpu可打开Netmarble Launcher。

三国志·战略版

PlayCover

1. 加载界面卡死无响应 ISSUE-023

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.s3.sgzzlb.cn.app/cn_appstore
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x00\xC0\x3D\x60\x02\x80\x3D\x00\x84\x40\xAD\x02\x8C\x41\xAD\x62\x8E\x01\xAD\x60\x86\x00\xAD\x00\x84\x42\xAD\x02\x1C\xC0\x3D"); exit 1 if $i < 0; seek F, $i - 4, 0; print F "\x1F\x00\x00\xB9"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

2. 登录后验证码不显示 ISSUE-025

原因分析 游戏会访问https://general.aligames.com/ieu-sdk-h5/challenge.html来显示验证码。

但Mac环境不满足网页代码中navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1的条件判断。

无法通过终端指令修复,请使用 PlayCover修改版 。

失控进化

PlayCover

1. 运行一分钟后闪退 ISSUE-012

使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“blockSleepSpamming”选项。

2. 麦克风问题 ISSUE-016

使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“checkMicPermissionSync”选项。

CrossOver

因反作弊无法运行。

实况足球(eFootball™)

PlayCover

1. 启动后黑屏 ISSUE-023

通过终端指令修复:

国服

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netease.pes.app/PesMobile-Shipping-Master
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x00\xC0\x3D\x60\x02\x80\x3D\x00\x84\x40\xAD\x02\x8C\x41\xAD\x62\x8E\x01\xAD\x60\x86\x00\xAD\x00\x84\x42\xAD\x02\x1C\xC0\x3D"); exit 1 if $i < 0; seek F, $i - 4, 0; print F "\x1F\x00\x00\xB9"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

国际服

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/jp.konami.pesactionmobile.app/PESmobile
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x00\xC0\x3D\x60\x02\x80\x3D\x00\x84\x40\xAD\x02\x8C\x41\xAD\x62\x8E\x01\xAD\x60\x86\x00\xAD\x00\x84\x42\xAD\x02\x1C\xC0\x3D"); exit 1 if $i < 0; seek F, $i - 4, 0; print F "\x1F\x00\x00\xB9"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

2. 登录后无限Loading ISSUE-001

通过终端指令修复:

国服

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netease.pes.app/PesMobile-Shipping-Master
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x2F\x00\x76\x00\x61\x00\x72\x00\x2F\x00\x00\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x2F\x00\x55\x00\x73\x00\x65\x00\x72\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

国际服

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/jp.konami.pesactionmobile.app/PESmobile
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x2F\x00\x76\x00\x61\x00\x72\x00\x2F\x00\x00\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x2F\x00\x55\x00\x73\x00\x65\x00\x72\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

CrossOver

1. 发烧游戏下载按钮没反应 ISSUE-026

通过终端指令修复:

sudo sysctl net.inet.tcp.sendspace=1048576

下载完成还原操作:

sudo sysctl net.inet.tcp.sendspace=131072

少女前线2:追放

PlayCover

1. 神秘弹窗

通过终端指令绕过:

TARGET=$(echo -n "dGVyc2FmZTI=" | base64 -d)
EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.Sunborn.SnqxExilium.app/Frameworks/$TARGET.framework/$TARGET
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/ShowMessageBoxWithTitle:Message:LeftBtn:RightBtn:/{found=1} found && /imp/{print $2; exit}')
printf '\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

2. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

CrossOver

因反作弊无法运行。

率土之滨

PlayCover

1. 启动闪退 ISSUE-018

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netease.stzb.app/client_app
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x2F\x70\x72\x69\x76\x61\x74\x65\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x00\x2F\x00\x00\x00\x00\x00\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

糖豆人

PlayCover

1. 启动闪退 ISSUE-028

该问题没有简单的修复方法,可选择以下方案:


2. 登录闪退

使用PlayCover Nightly版,右键游戏图标 - 设置 - 图像设置,分辨率选择“settings.picker.adaptiveRes.6(Resizable)”。登录成功后可以改回原来的设置。

如果还是闪退,请尝试将iOS机型改为iPhone。

3. 登录失败,无法连接到服务器

打开系统设置 - 通用- 语言与地区 - 应用程序,添加糖豆人并选择英语。

4. 队伍语音设置界面无法关闭

右键游戏图标 - 设置 - 键盘映射设置,禁用“按键映射布局”。

操作完成后再重新打开这个选项。

天涯明月刀手游

PlayCover

1. 屏幕方向错误 ISSUE-013

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.wuxia.app/wuxia
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/UnityAppController/{found=1} found && /createRootViewController$/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x00\x80\xD2' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000+0x18)) conv=notrunc
printf '\x82\x00\x80\xD2' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000+0x6C)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

王者荣耀世界

PlayCover

1. 启动闪退 ISSUE-001

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.ngr.app/NGR
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x2F\x00\x76\x00\x61\x00\x72\x00\x2F\x00\x00\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x2F\x00\x55\x00\x73\x00\x65\x00\x72\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

2. 鼠标点击异常 ISSUE-003

点不了扫码按钮,设置界面点不了帧率选项。

使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

3. 麦克风问题 ISSUE-016

使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“checkMicPermissionSync”选项。

CrossOver

因反作弊无法运行。

蔚蓝档案

PlayCover

1. 各服务器情况

国服:正常运行。
日服:需使用 PlayCover修改版 。
国际服:因反作弊无法运行。

2. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

CrossOver

目前无法运行,启动后黑屏卡住,不支持VP9视频编码。

相关帖子:CrossOver Mac forum

Wine(国际服)

参考教程:Blue Archive Steam讨论区

Important

Wine Staging自11.7版本开始移除了对Steam和DXMT的内置支持,因此我们无法使用最新版本的Wine Staging。

1. 安装Wine

下载Wine Staging 11.5 + DXMT 0.71,解压后拖到应用程序文件夹。

执行以下指令(需要输入开机密码):

sudo ln -s "/Applications/Wine Staging.app/Contents/Resources/wine/bin/wine" /usr/local/bin/wine
sudo ln -s "/Applications/Wine Staging.app/Contents/Resources/wine/bin/wineserver" /usr/local/bin/wineserver

2. 安装Homebrew

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

3. 安装GStreamer

brew install --cask gstreamer-runtime

4. 安装Steam

若系统提示“无法验证Wine Staging”,请前往系统设置 - 隐私与安全性 - 点击“仍要打开“。

brew install winetricks
winetricks fakechinese
winetricks steam

5. 运行Steam

wine ~/.wine/drive_c/Program\ Files\ \(x86\)/Steam/Steam.exe

卸载步骤

a. 执行以下指令:

rm -rf ~/.wine
brew uninstall winetricks
brew uninstall --cask gstreamer-runtime

b. 删掉应用程序文件夹里的Wine Staging。

Wine(日服)

Important

Wine Staging自11.7版本开始移除了对DXMT的内置支持,因此我们无法使用最新版本的Wine Staging。

1. 安装Wine

下载Wine Staging 11.5 + DXMT 0.71,解压后拖到应用程序文件夹。

执行以下指令(需要输入开机密码):

sudo ln -s "/Applications/Wine Staging.app/Contents/Resources/wine/bin/wine" /usr/local/bin/wine
sudo ln -s "/Applications/Wine Staging.app/Contents/Resources/wine/bin/wineserver" /usr/local/bin/wineserver

2. 安装GStreamer

从GStreamer官网下载runtime installer并安装。

也可以通过Homebrew安装,具体请看国际服版本的教程。

3. 安装游戏启动器

若系统提示“无法验证Wine Staging”,请前往系统设置 - 隐私与安全性 - 点击“仍要打开“。

wine ~/Downloads/BlueArchive_JP_Gamelauncher-1.7.2-setup.exe

4. 运行游戏启动器

第一次启动游戏可能会黑屏几分钟,请耐心等待。

wine ~/.wine/drive_c/YostarGames/BlueArchive_JP_Gamelauncher/BlueArchive_JP_Gamelauncher.exe --in-process-gpu

已知问题

游戏过程中会弹出“Vuplex WebView.vuplex”报错,且公告界面内容不显示。

需要使用DXMT 0.72才能解决Vuplex报错,但是DXMT 0.72会有黑屏卡住的问题,所以暂时无解。遇到报错弹窗直接点“关闭”即可。

汉化步骤

a. 按照汉化教程下载汉化版启动器BlueArchive_JP_Gamelauncher.zip并解压。

b. 打开游戏安装目录:

open ~/.wine/drive_c/YostarGames/

c. 将原版启动器进行重命名备份,然后放入汉化版启动器

d. 使用同样的命令运行启动器

卸载步骤

点击下载 uninstall_gstreamer_macos.sh

a. 删除容器:rm -rf ~/.wine

b. 卸载GStreamer:sh uninstall_gstreamer_macos.sh

c. 删掉应用程序文件夹里的Wine Staging。

Wine小知识

MetalHUD

在wine命令前添加MTL_HUD_ENABLED=1,例如:

MTL_HUD_ENABLED=1 wine /path/to/exe

高分辨率模式

# 启用高分辨率
wine reg add "HKCU\\Software\\Wine\\Mac Driver" /v RetinaMode /t REG_SZ /d y /f
# 禁用高分辨率
wine reg delete "HKCU\\Software\\Wine\\Mac Driver" /v RetinaMode /f

退出所有程序

wineserver -k

向僵尸开炮

App Store

1. 启动闪退 ISSUE-027

通过终端指令修复:

sudo mkdir -p /var/mobile/Library/UserConfigurationProfiles/PublicInfo
sudo touch /var/mobile/Library/UserConfigurationProfiles/PublicInfo/MCMeta.plist

PlayCover

1. 启动闪退 ISSUE-027

通过终端指令修复:

sudo mkdir -p /var/mobile/Library/UserConfigurationProfiles/PublicInfo
sudo touch /var/mobile/Library/UserConfigurationProfiles/PublicInfo/MCMeta.plist

2. 画面显示不全

右键游戏图标 - 设置 - 图像设置,分辨率选择“默认”,启用“修复窗口化显示问题”,旁边的下拉框选择“备用”。

3. PlayCover Nightly版启动闪退

原因分析:游戏使用到了fishhook,与PlayTools代码中的DYLD_INTERPOSE(pt_open, open)产生冲突导致闪退。

无法通过终端指令修复,请使用 PlayCover修改版 。

星塔旅人

App Store

iOS版本,正常运行但存在一些问题。

PlayCover

1. 运行一分钟后闪退 ISSUE-012

使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“blockSleepSpamming”选项。

2. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

CrossOver

因反作弊无法运行。

学园偶像大师

PlayCover

1. 画面显示不全

使用PlayCover Nightly版,右键游戏图标 - 设置 - 图像设置,分辨率选择“settings.picker.adaptiveRes.6(Resizable)”。

2. 黑屏问题

拖拽窗口边缘,调整至对应横屏或竖屏的大小即可。

3. 登录状态丢失 ISSUE-005

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/jp.co.bandainamcoent.BNEI0421.app/Frameworks/UnityFramework.framework/UnityFramework
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\xB3\x05\x80\xD2\x13\x00\xFA\xF2\x60\x6E\x00\xD1") - 0x54; exit 1 if $i < 0; seek F, $i, 0; my $val = unpack("V", do { read(F, my $buf, 4); $buf }); my $val2 = unpack("V", do { read(F, my $buf, 4); $buf }); my $offset = ((($val >> 5) & 0x7FFFF) << 2) | (($val >> 29) & 0x3); my $page = ($i >> 12) + $offset; my $i = index($d, "\x00\x00\x80\xD2\x01\x00\xFE\xD2\x12\x00\x00\x14") - 0x318; exit 1 if $i < 0; my $j = $i + 0x2A0; seek F, $j, 0; my $offset = $page - ($j >> 12); my $val = (1 << 31) | (($offset & 0x3) << 29) | (0x10 << 24) | ((($offset >> 2) & 0x7FFFF) << 5); print F pack("V", $val); print F pack("V", $val2); my $j = $i + 0x2E4; seek F, $j, 0; print F "\xFB\x03\x00\xF9\xF4\x03\x16\xAA\xD3\x00\x00\x14"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE

或者保存以下内容为script.sh,通过终端指令sh script.sh运行:

#!/bin/zsh

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/jp.co.bandainamcoent.BNEI0421.app/Frameworks/UnityFramework.framework/UnityFramework

perl -e '
open F, "+<:raw", $ARGV[0] or die $!;
local $/;
my $d = <F>;

my $i = index($d, "\xB3\x05\x80\xD2\x13\x00\xFA\xF2\x60\x6E\x00\xD1") - 0x54;
exit 1 if $i < 0;
seek F, $i, 0;
my $val = unpack("V", do { read(F, my $buf, 4); $buf });
my $val2 = unpack("V", do { read(F, my $buf, 4); $buf });
my $offset = ((($val >> 5) & 0x7FFFF) << 2) | (($val >> 29) & 0x3);
my $page = ($i >> 12) + $offset;

my $i = index($d, "\x00\x00\x80\xD2\x01\x00\xFE\xD2\x12\x00\x00\x14") - 0x318;
exit 1 if $i < 0;

my $j = $i + 0x2A0;
seek F, $j, 0;
my $offset = $page - ($j >> 12);
my $val = (1 << 31) | (($offset & 0x3) << 29) | (0x10 << 24) | ((($offset >> 2) & 0x7FFFF) << 5);
print F pack("V", $val);
print F pack("V", $val2);

my $j = $i + 0x2E4;
seek F, $j, 0;
print F "\xFB\x03\x00\xF9\xF4\x03\x16\xAA\xD3\x00\x00\x14";

close F;
' $EXECUTABLE

codesign -fs- $EXECUTABLE

CrossOver

因反作弊无法运行。

燕云十六声

Mac原生版本

官网可下载:https://adl.netease.com/d/g/yysls/c/mac

PlayCover

1. 画面拉伸问题

右键游戏图标 - 设置 - 图像设置,启用“修复窗口化显示问题”。

2. 切换界面时长时间黑屏 ISSUE-011

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netease.yyslscn.app/Game
FUNC_ADDR=$(otool -Iv "$EXECUTABLE" | grep _os_proc_available_memory | head -n1 | awk '{print $1}')
printf '\x20\x00\xC0\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

CrossOver

正常运行。

异环

App Store

Mac原生版本,正常运行。

PlayCover

1. 中文系统下启动闪退 ISSUE-002

PlayCover Nightly版已修复此问题。

2. 启动闪退 ISSUE-011

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.pwrd.yh.ios.app/HTGame-IOS-Shipping
FUNC_ADDR=$(otool -Iv "$EXECUTABLE" | grep _os_proc_available_memory | head -n1 | awk '{print $1}')
printf '\x20\x00\xC0\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

3. 未获取到有效服务器 ISSUE-001

游戏跳过更新资源直接到达登录界面。

通过终端指令修复:

rm -r /Users/$USER/Library/Containers/com.pwrd.yh.ios/Data/Documents/Users/$USER/Library/Containers/com.pwrd.yh.ios/Data && ln -sf /Users/$USER/Library/Containers/com.pwrd.yh.ios/Data /Users/$USER/Library/Containers/com.pwrd.yh.ios/Data/Documents/Users/$USER/Library/Containers/com.pwrd.yh.ios/Data

4. 键鼠如何操作载具

点击查看教程

5. 键鼠操作Bug

  • 视角无故缩放:右键游戏图标 - 设置 - 键盘映射 - 禁用滚轮。
  • 视角无法移动:尝试同时按下鼠标左键和鼠标右键。

6. 手柄键位不显示

先启动游戏再连接手柄,或者在游戏过程中断开重连一次手柄。

7. 运行帧率低/发热严重

右键游戏图标,选择“显示应用数据”,进入异环/Data/Documents/HT/Saved/Config/IOS,创建DeviceProfiles.ini,然后用文本编辑打开DeviceProfiles.ini:

[iPadPro5_129 DeviceProfile]
CVars=r.MobileContentScaleFactor=1.0

右键游戏图标 - 设置 - 图像设置,查看选定的iOS机型:

  • 如果是M1 iPad,则保持不变
  • 如果是M2 iPad,则将iPadPro5_129改为iPadPro6_129
  • 如果是M4 iPad,则将iPadPro5_129改为iPadPro7_129

可任意修改等号后面的数值。数值越小,画面越糊,运行越流畅,发热越少。

永恒之塔2

App Store

iOS版本,正常运行。

Tip

访达菜单 - 前往 - 前往文件夹,输入~/Library/Containers/AION2可打开应用数据目录。

解锁60帧和减少发热的方法请看下文。

PlayCover

1. 鼠标点击UI无反应 ISSUE-003

使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

2. 不停弹出错误报告 ISSUE-010

PlayCover Nightly版已修复此问题。

3. 解锁60帧

右键游戏图标,选择“显示应用数据”,进入AION2/Data/Library/AION2/Saved/Config/IOS,创建Engine.ini,然后用文本编辑打开Engine.ini:

[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
FrameRateLock=PUFRL_60

如果需要更高的帧率,可改成:

[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
FrameRateLock=PUFRL_None

4. 运行帧率低/发热严重

右键游戏图标,选择“显示应用数据”,进入AION2/Data/Library/AION2/Saved/Config/IOS,创建DeviceProfiles.ini,然后用文本编辑打开DeviceProfiles.ini:

[iPadPro5_129 DeviceProfile]
CVars=r.MobileContentScaleFactor=1.0

可任意修改等号后面的数值。数值越小,画面越糊,运行越流畅,发热越少。

CrossOver

因反作弊无法运行。

添加命令行参数--in-process-gpu可打开PURPLE平台。

战舰世界:传奇

PlayCover

1. 启动闪退1 ISSUE-011

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.wg.wowslegends.app/Legends
FUNC_ADDR=$(otool -Iv "$EXECUTABLE" | grep _os_proc_available_memory | head -n1 | awk '{print $1}')
printf '\x20\x00\xC0\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

2. 启动闪退2

原因分析

游戏会查找文件路径中的Legends.app/,但PlayCover中的安装目录命名是com.wg.wowslegends.app,文件路径中并没有包含Legends.app/,所以这里需要通过补丁将游戏代码中的字符串Legends.app/修改为字符串legends.app/。

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.wg.wowslegends.app/Legends
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x4C\x65\x67\x65\x6E\x64\x73\x2E\x61\x70\x70\x2F\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x6C"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

3. 画面显示不全

右键游戏图标 - 设置 - 图像设置,启用“修复窗口化显示问题”选项。

战双帕弥什

PlayCover

1. 启动闪退 ISSUE-024

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“ignoreUnityKeyboardInitializationError”选项。

CrossOver

https://github.com/reiserFSs/pgrpatcher

战争雷霆手游

PlayCover

1. 启动闪退

原因分析

游戏会尝试删除game文件夹下的miniUi.vromfs.bin文件,成功删除后会导致后续加载miniUi.vromfs.bin失败。手机上不存在这个问题是因为手机上的game文件夹是只读的,删除不了。


按照以下步骤操作:

  • 重装一次IPA。
  • 右键游戏图标 - 在访达中查看 - 右键游戏文件 - 查看包内容。
  • 找到game文件夹 - 右键显示简介 - 共享与权限,将本用户的权限改为“只读”。
  • 运行游戏。

Warning

卸载游戏的时候最好先把权限改回去,否则PlayCover会出现卸载失败的情况。


2. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

植物大战僵尸2

PlayCover

1. 屏幕方向错误

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.popcap.ios.chs.PVZ2.app/PvZ2
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/name .+ GameViewController/{found=1} found && /supportedInterfaceOrientations/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x02\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

棕色尘埃2

PlayCover

1. 谷歌登录报错

登录时提示“HAS_NO_AUTH_IN_KEYCHAIN”。

可通过终端指令修复:

defaults delete com.neowizgames.game.browndust2ios neo_google_user_id

2. 登录状态丢失 ISSUE-005

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.neowizgames.game.browndust2ios.app/Frameworks/FirebaseAuth.framework/FirebaseAuth
printf '\x20\x07\x00\xF0\x00\x80\x2A\x91\x01\x05\x00\xB0\x21\xE0\x19\x91' | dd of=$EXECUTABLE bs=1 seek=$((0x35C78)) conv=notrunc
printf '\xF4\x03\x18\xAA\x8F\x00\x00\x14' | dd of=$EXECUTABLE bs=1 seek=$((0x35D60)) conv=notrunc
printf '\x1F\x20\x03\xD5' | dd of=$EXECUTABLE bs=1 seek=$((0x360C4)) conv=notrunc
codesign -fs- $EXECUTABLE

3. 使用苹果帐号登录

请严格按照以下步骤操作:

  1. 确认是否已执行上述第二条中的指令
  2. 确认是否启用了PlayChain(右键游戏图标 - 设置 - 绕过设置 - 启用PlayChain)
  3. 禁用SIP
  4. 正常载入系统,终端执行sudo nvram boot-args="amfi_get_out_of_my_way=0x1 ipc_control_port_options=0",重启电脑
  5. 正常载入系统,从PlayCover界面打开游戏并登录苹果帐号,关闭游戏后等待10秒
  6. 启用SIP
  7. 正常载入系统,测试苹果帐号登录状态

Warning

受限于PlayCover保存PlayChain数据的实现方式。

  1. 关闭游戏后,距离下一次打开最好超过10秒,否则会造成PlayChain数据丢失。
  2. 每次都从PlayCover界面启动游戏,不要从程序坞、启动台或访达界面启动游戏。

4. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

NIKKE

PlayCover

1. 修复启动卡死及显示问题

国际服:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.proximabeta.nikke.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/INTLUtilsIOS/{found=1} found && /swizzlingOriginalClass:swizzledClass:originalSEL:swizzledSEL:/{f=1} f && /imp/{print $2; exit}')
printf '\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/UnityDefaultViewController/{found=1} found && /supportedInterfaceOrientations/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x03\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

港澳台服:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.gamamobi.nikke.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/INTLUtilsIOS/{found=1} found && /swizzlingOriginalClass:swizzledClass:originalSEL:swizzledSEL:/{f=1} f && /imp/{print $2; exit}')
printf '\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/UnityDefaultViewController/{found=1} found && /supportedInterfaceOrientations/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x03\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

国服:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.nikke.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/UnityDefaultViewController/{found=1} found && /supportedInterfaceOrientations/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x03\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

2. 国服兑换码界面问题 ISSUE-019

通过终端指令修复:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.tencent.nikke.app/Frameworks/MSDKPIXWebView.framework/MSDKPIXWebView
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/MSDKPIXWKWebViewController/{found=1} found && /supportedInterfaceOrientations/{f=1} f && /imp/{print $2; exit}')
printf '\x00\x03\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

3. CPU占用异常偏高 ISSUE-004

使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

CrossOver

因反作弊无法运行。

Warframe

PlayCover

1. 恢复SIP后登录状态丢失

通过补丁指令跳过检查:

EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.digitalextremes.warframemobile.app/App
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\xC8\xED\x8D\xD2\x88\xCE\xA8\xF2\xE8\xAD\xCE\xF2\xC8\x8D\xEC\xF2"); exit 1 if $i < 0; seek F, $i - 0x4D4, 0; print F "\x39\x00\x80\xD2"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

CrossOver

正常运行。

问题列表

ISSUE-001

虚幻引擎文件路径错误

常见表现

加载进度卡住,加载过程中提示存储空间不足,加载过程中提示文件操作失败,加载过程中闪退,启动阶段黑屏。

相关源码

虚幻引擎 IOSPlatformFile.cpp

FString FIOSPlatformFile::ConvertToPlatformPath(const FString& Filename, bool bForWrite, bool bIsPublicWrite)
{
	FString Result = Filename;
	if (Result.StartsWith(TEXT("/var/")))
	{
		return Result;
	}
	
	if (bForWrite)
	{
		static FString PublicWritePathBase = FString([NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]) + TEXT("/");
		static FString PrivateWritePathBase = FString([NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]) + TEXT("/");
		return (bIsPublicWrite ? PublicWritePathBase : PrivateWritePathBase) + Result;
	}
	else
	{
		static FString ReadPathBase = FString([[NSBundle mainBundle] bundlePath]) + TEXT("/cookeddata/");
		return ReadPathBase + Result.ToLower();
	}
}

原因分析

虚幻引擎根据字符串是否以/var/开头,来判断字符串是否绝对路径,但macOS的绝对路径并不是以/var/开头的,因此导致各种问题。

iOS的绝对路径:/var/mobile/Containers/Data/Application/{GUID}/Documents

macOS的绝对路径:/Users/{USER}/Containers/{BUNDLE_ID}/Data/Documents

解决方法

文件链接法

BUNDLE_ID=com.companyname.appname

rm -r /Users/$USER/Library/Containers/$BUNDLE_ID/Data/Documents/Users/$USER/Library/Containers/$BUNDLE_ID/Data && ln -sf /Users/$USER/Library/Containers/$BUNDLE_ID/Data /Users/$USER/Library/Containers/$BUNDLE_ID/Data/Documents/Users/$USER/Library/Containers/$BUNDLE_ID/Data

rm -r /Users/$USER/Library/Containers/$BUNDLE_ID/Data/Library/Users/$USER/Library/Containers/$BUNDLE_ID/Data && ln -sf /Users/$USER/Library/Containers/$BUNDLE_ID/Data /Users/$USER/Library/Containers/$BUNDLE_ID/Data/Library/Users/$USER/Library/Containers/$BUNDLE_ID/Data

补丁法

修改常量字符串/var/为/User(保持字符串长度不变)

BUNDLE_ID=com.companyname.appname
BUNDLE_PATH=~/Library/Containers/io.playcover.PlayCover/Applications/$BUNDLE_ID.app
EXECUTABLE=$BUNDLE_PATH/$(/usr/libexec/PlistBuddy -c "Print :CFBundleExecutable" $BUNDLE_PATH/Info.plist)
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x2F\x00\x76\x00\x61\x00\x72\x00\x2F\x00\x00\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x2F\x00\x55\x00\x73\x00\x65\x00\x72\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

ISSUE-002

虚幻引擎字符串解码失败导致闪退

常见表现

系统语言为中文时,启动游戏立刻闪退。

相关源码

虚幻引擎 IOSPlatformMisc.cpp

typedef struct __Blob {
    uint32_t magic;
    uint32_t length;
    char data[];
} CS_GenericBlob;

extern NSString *EntitlementsData(void)
{
	//...
	
	CS_GenericBlob blob;
	Count = fread(&blob, sizeof(CS_GenericBlob), 1, file);
	
	if (__builtin_bswap32(blob.magic) == 0xfade7171)
	{
		uint32 blobLength = ntohl(blob.length);
		char data[blobLength];
		fread(&data[0], sizeof(char) * blobLength, 1, file);
		NSString *stringFromData = [NSString stringWithFormat: @"%s", data];
		NSLog(@"%@", stringFromData);
		fclose(file);
		return stringFromData;
	}
	
	//...
}

原因分析

data的长度应为blobLength减去8,而不是等于blobLength。由于fread()多读取了8个字节,最终调用[NSString stringWithFormat:]时字符串解码失败导致闪退。

解决方法

方法一:PlayCover Nightly版已修复此问题。

方法二:打开系统配置文件~/.CFUserTextEncoding,修改冒号前的部分为0x0,修改后重启电脑。

方法三:修改系统语言为英文。

ISSUE-003

虚幻引擎鼠标点击异常

常见表现

鼠标点击UI无反应,屏幕上出现两个点击特效。

原因分析

游戏同时捕获了触屏输入和鼠标输入,且由于iOS并没有提供获取鼠标位置的API,所以游戏记录的鼠标位置始终为屏幕左上角 (0, 0)。

每当玩家按下鼠标,都会在鼠标所在位置和屏幕左上角执行一次点击,从而出现点击冲突的情况。

解决方法

使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。

ISSUE-004

CPU占用异常偏高

常见表现

CPU占用异常偏高,电脑发热厉害。

此问题通常会在Unity游戏和使用了重力感应功能(摇一摇)的App中出现。

相关源码

UIKitMacHelper.framework

Mac运行iOS应用时,CMMotionManager的底层实现为UINSVirtualMotionDevice。

void -[UINSVirtualMotionDevice startAccelerometerUpdates]
{
	if (!_accelerometerDispatchIsActive)
	{
	    dispatch_resume(_accelerometerDispatchSource);
	    _accelerometerDispatchIsActive = YES;
	}
}

id -[UINSVirtualMotionDevice accelerometerData]
{
	if (!_accelerometerDispatchIsActive)
	{
		dispatch_resume(_accelerometerDispatchSource);
		_accelerometerDispatchIsActive = YES;
	}
	return _accelerometerData;
}

Unity引擎 iPhone_Sensors.mm

extern "C" void UnityCoreMotionStart()
{
    if (sMotionManager.accelerometerAvailable)
    {
        const int frequency = UnityGetAccelerometerFrequency();
        if (frequency > 0)
        {
            sMotionManager.accelerometerUpdateInterval = 1.0f / frequency;
            [sMotionManager startAccelerometerUpdates];
        }
    }
}

extern "C" void UnityUpdateAccelerometerData()
{
	CMAccelerometerData* data = sMotionManager.accelerometerData;
	if (data != nil)
	{
		Vector3f res = UnityReorientVector3(data.acceleration.x, data.acceleration.y, data.acceleration.z);
		UnityDidAccelerate(res.x, res.y, res.z, data.timestamp);
	}
}

原因分析

第一个问题:CMMotionManager的默认更新间隔为0秒,如果不修改更新间隔,直接调用startAccelerometerUpdates就会导致频繁更新,从而占用大量CPU时间。

第二个问题:访问CMMotionManager的accelerometerData数据时,会自动触发startAccelerometerUpdates,也就是说这个接口有副作用。

而Unity引擎在某种情况下,实例化了CMMotionManager,没有修改更新间隔,也没有主动调用startAccelerometerUpdates。

但是因为之后读取了accelerometerData,间接触发了startAccelerometerUpdates,从而导致更新间隔0秒的频繁更新。

解决方法

玩家方面:使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。

开发者方面:调整默认的更新间隔,避免使用0秒间隔。

extern "C" void UnityCoreMotionStart()
{
	//...
	bool initMotionManager = (sMotionManager == nil);
    if (initMotionManager) {
        sMotionManager = [[CMMotionManager alloc] init];
        sMotionManager.accelerometerUpdateInterval = 0.01;
        sMotionManager.deviceMotionUpdateInterval = 0.01;
        sMotionManager.gyroUpdateInterval = 0.01;
    }
    //...
}

ISSUE-005

FirebaseSDK读取登录状态失败

常见表现

使用谷歌帐号登录的游戏,第二次打开时出现闪退,或是需要重新登录。

相关源码

FIRAuthKeychainServices.m

- (nullable NSData *)itemWithQuery:(NSDictionary *)query error:(NSError **_Nullable)error {
  NSMutableDictionary *returningQuery = [query mutableCopy];
  returningQuery[(__bridge id)kSecReturnData] = @YES;
  returningQuery[(__bridge id)kSecReturnAttributes] = @YES;
  returningQuery[(__bridge id)kSecMatchLimit] = @2;

  CFArrayRef result = NULL;
  OSStatus status =
      SecItemCopyMatching((__bridge CFDictionaryRef)returningQuery, (CFTypeRef *)&result);

  if (status == noErr && result != NULL) {
    NSArray *items = (__bridge_transfer NSArray *)result;
    if (items.count == 0) {
      return nil;
    }
    //...
  }
}

原因分析

FirebaseSDK传入参数kSecMatchLimit=2,并期望返回结果是一个NSArray。

但目前PlayCover的代码并没有正确处理kSecMatchLimit=2的情况,PlayCover返回的是一个NSDictionary,类型不匹配导致出错。

解决方法

根本解决方法:修改PlayCover代码。

临时解决方法一:每次打开游戏之前,右键游戏图标,清除PlayChain数据可解决闪退。

临时解决方法二:插入跳转指令,从A处直接跳转到B处。

Firebase SDK旧版本(Objcetive-C):

- (nullable NSData *)itemWithQuery:(NSDictionary *)query error:(NSError **_Nullable)error {
  CFArrayRef result = NULL;
  OSStatus status =
      SecItemCopyMatching((__bridge CFDictionaryRef)returningQuery, (CFTypeRef *)&result);

  if (status == noErr && result != NULL) {
    NSArray *items = (__bridge_transfer NSArray *)result;
    
    /* --------- A --------- */
    if (items.count == 0) { 
      // throw error
    } else if (items.count > 1) {
      // log("Keychain query returned multiple results")
    }

	NSDictionary *item = items[0];
	
	/* --------- B --------- */
    return item[(__bridge id)kSecValueData];
  }
}
0x4C8A04    STR    XZR, [SP,#0x130+result]
0x4C8A08    ADD    X1, SP, #0x130+result ; result
0x4C8A0C    MOV    X0, X19 ; query
0x4C8A10    BL     _SecItemCopyMatching
0x4C8A14    MOV    X3, X0
0x4C8A18    CBNZ   W0, loc_4C8B4C
0x4C8A1C    LDR    X20, [SP,#0x130+result]
0x4C8A20    CBZ    X20, loc_4C8B4C
0x4C8A24    MOV    X0, X20
0x4C8A28    BL     _objc_msgSend$count   ; 改为B #0x110,跳转至0x4C8B38
0x4C8A2C    CBZ    X0, loc_4C8BCC
0x4C8A30    MOV    X0, X20
0x4C8A34    BL     _objc_msgSend$count
0x4C8A38    CMP    X0, #2
0x4C8A3C    B.CC   loc_4C8A64

0x4C8B1C loc_4C8B1C
0x4C8B1C    MOV    X0, X21
0x4C8B20    BL     _objc_release
0x4C8B24    MOV    X0, X21
0x4C8B28    MOV    X2, #0
0x4C8B2C    BL     _objc_msgSend$objectAtIndexedSubscript_
0x4C8B30    MOV    X29, X29
0x4C8B34    BL     _objc_retainAutoreleasedReturnValue
0x4C8B38    MOV    X21, X0               ; 跳转目标位置
0x4C8B3C    ADRP   X8, #_kSecValueData_ptr@PAGE
0x4C8B40    LDR    X8, [X8,#_kSecValueData_ptr@PAGEOFF]
0x4C8B44    LDR    X2, [X8]
0x4C8B48    B      loc_4C8BA8

0x4C8BA8 loc_4C8BA8
0x4C8BA8    BL     _objc_msgSend$objectForKeyedSubscript_
0x4C8BAC    MOV    X29, X29
0x4C8BB0    BL     _objc_retainAutoreleasedReturnValue
0x4C8BB4    MOV    X22, X0
0x4C8BB8    MOV    X0, X21
0x4C8BBC    BL     _objc_release         ; 屏蔽这条指令,避免重复调用_objc_release
0x4C8BC0    B      loc_4C8C04

Firebase SDK新版本(Swift):

func getItemLegacy(query: [String: Any]) throws -> Data? {
	var returningQuery = query
	returningQuery[kSecReturnData as String] = true
	returningQuery[kSecReturnAttributes as String] = true
	returningQuery[kSecMatchLimit as String] = 2
	
	var result: AnyObject?
	let status = keychainStorage.get(query: returningQuery, result: &result)
	
	if let items = result as? [[String: Any]], status == noErr {
      /* --------- A --------- */
	  if items.isEmpty {
	    // throw error
	  } else if items.count > 1 {
	    // log("Keychain query returned multiple results")
	  }
		
      let item = items[0];
	  
	  /* --------- B --------- */
	  return item[kSecValueData as String] as? Data
	}
}

情况一:存在FirebaseAuth.framework

0x36A94    ADRL    X0, _$sSaySDySSypGGMd    ; 修改这两行,将[[String: Any]]类型改为[String: Any]类型
0x36A9C    ADRL    X1, _$sSaySDySSypGGMR    ; 在AuthErrorUtils.extractJSONObjectFromString()中能找到[String: Any]的type_metadata
0x36AA4    BL      ___swift_instantiateConcreteTypeFromMangledNameV2
0x36AA8    MOV     X3, X0
0x36AAC    ADRP    X8, #_$syXlN_ptr@PAGE
0x36AB0    LDR     X8, [X8,#_$syXlN_ptr@PAGEOFF]
0x36AB4    ADD     X0, SP, #0xB0+var_90
0x36AB8    ADD     X1, SP, #0xB0+var_70
0x36ABC    ADD     X2, X8, #8
0x36AC0    MOV     W4, #6
0x36AC4    BL      _swift_dynamicCast
0x36AC8    TBZ     W0, #0, loc_36B08
0x36ACC    LDR     X23, [SP,#0xB0+var_90]
0x36AD0    BL      _$s6Darwin5noErrs5Int32Vvg ; noErr.getter
0x36AD4    CMP     W20, W0
0x36AD8    B.NE    loc_36B00
0x36ADC    LDR     X8, [X23,#0x10]
0x36AE0    STP     X26, X8, [SP,#0xB0+var_A0]
0x36AE4    CMP     X8, #1                       ; 改为MOV X20, X23
0x36AE8    B.EQ    loc_36CB0                    ; 跳转至0x36D90

0x36D70 loc_36D70
0x36D70    LDR     X8, [X23,#0x10]
0x36D74    LDR     X19, [SP,#0xB0+var_A8]
0x36D78    CBZ     X8, loc_36F14
0x36D7C    LDR     X20, [X23,#0x20]
0x36D80    MOV     X0, X20
0x36D84    BL      _swift_bridgeObjectRetain
0x36D88    MOV     X0, X23
0x36D8C    BL      _swift_bridgeObjectRelease
0x36D90    ADRP    X8, #_kSecValueData_ptr@PAGE  ; 跳转目标位置
0x36D94    LDR     X8, [X8,#_kSecValueData_ptr@PAGEOFF]
0x36D98    LDR     X0, [X8]
0x36D9C    BL      _$sSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ

情况二:不存在FirebaseAuth.framework,和其他代码编译在一起了

0x6D96C    ADRL    X0, unk_BD971F8      ; 修改此行,将[[String: Any]]类型改为[String: Any]类型
0x6D974    BL      sub_35660            ; 搜索字符串Error while converting assumed plist to dictionary,往前找dynamicCast,可找到[String: Any]的type_metadata
0x6D978    MOV     X3, X0
0x6D97C    ADRP    X8, #_$syXlN_ptr@PAGE
0x6D980    LDR     X8, [X8,#_$syXlN_ptr@PAGEOFF]
0x6D984    ADD     X2, X8, #8
0x6D988    ADD     X0, SP, #0xB0+var_A0
0x6D98C    ADD     X1, SP, #0xB0+var_80
0x6D990    MOV     W4, #6
0x6D994    BL      j__swift_dynamicCast
0x6D998    TBZ     W0, #0, loc_6D9D0
0x6D99C    LDR     X22, [SP,#0xB0+var_A0]
0x6D9A0    BL      j__$s6Darwin5noErrs5Int32Vvg ; noErr.getter
0x6D9A4    CMP     W20, W0
0x6D9A8    B.NE    loc_6D9C8
0x6D9AC    LDR     X28, [X22,#0x10]
0x6D9B0    CMP     X28, #1                      ; 改为STR X27, [SP](暂存Exception信息)
0x6D9B4    B.EQ    loc_6DB88                    ; 改为MOV X20, X22
0x6D9B8    CBNZ    X28, loc_6DA70               ; 跳转至0x6DD04

0x6DCE4 loc_6DCE4
0x6DCE4    MOV     X0, X22
0x6DCE8    BL      j__swift_bridgeObjectRelease
0x6DCEC    ADRL    X1, unk_BD96718
0x6DCF4    ADD     X0, SP, #0xB0+var_80
0x6DCF8    BL      sub_35728
0x6DCFC    MOV     X0, X22
0x6DD00    BL      j__swift_bridgeObjectRelease
0x6DD04    ADRP    X8, #_kSecValueData_ptr@PAGE  ; 跳转目标位置
0x6DD08    LDR     X8, [X8,#_kSecValueData_ptr@PAGEOFF]
0x6DD0C    LDR     X0, [X8]
0x6DD10    BL      j__$sSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ

ISSUE-006

虚幻引擎打不了字

常见表现

启用按键映射的情况下,打不了字。

相关源码

虚幻引擎 IOSView.h

@interface FIOSView : UIView <UIKeyInput, UITextInput>
{
	//... 
}

PlayTools ControlMode.swift

if PlaySettings.shared.noKMOnInput {
	NotificationCenter.default.addObserver(forName: UITextField.textDidEndEditingNotification, object: nil, queue: .main) { _ in
		ModeAutomaton.onUITextInputEndEdit()
	}
	NotificationCenter.default.addObserver(forName: UITextField.textDidBeginEditingNotification, object: nil, queue: .main) { _ in
		ModeAutomaton.onUITextInputBeginEdit()
	}
}

原因分析

目前PlayCover的智能按键映射只会监听UITextField和UITextView的开始输入、停止输入事件。

但虚幻引擎启用Use Integrated Keyboard后,文本输入将不会调用UITextField,而是直接通过UIKeyInput接口实现,也就不会产生UITextField的相关事件广播。

解决方法

临时解决方法:

右键游戏图标 - 设置 - 键盘映射设置,禁用“按键映射布局” 或 禁用“智能按键映射”。

临时修复代码:

PlayTools NSObject+Swizzle.m

手动发送相关事件广播。

- (BOOL)hook_FIOSView_becomeFirstResponder {
    BOOL ret = [self hook_FIOSView_becomeFirstResponder];
    [[NSNotificationCenter defaultCenter] postNotificationName:UITextFieldTextDidBeginEditingNotification
                                                        object:nil];
    return ret;
}

- (BOOL)hook_FIOSView_resignFirstResponder {
    BOOL ret = [self hook_FIOSView_resignFirstResponder];
    [[NSNotificationCenter defaultCenter] postNotificationName:UITextFieldTextDidEndEditingNotification
                                                        object:nil];
    return ret;
}

[objc_getClass("FIOSView") swizzleInstanceMethod:@selector(becomeFirstResponder) withMethod:@selector(hook_FIOSView_becomeFirstResponder)];
[objc_getClass("FIOSView") swizzleInstanceMethod:@selector(resignFirstResponder) withMethod:@selector(hook_FIOSView_resignFirstResponder)];

ISSUE-007

摇杆映射问题

PlayCover默认支持固定摇杆模式,请在游戏设置中查找是否有“固定摇杆”的选项。

或者调整为跟随式摇杆模式:

  • PlayCover 稳定版:在编辑模式中选中WASD控件,放大至覆盖半个窗口。
  • PlayCover Nightly版:在编辑模式中选中WASD控件,更改为自由摇杆模式。

ISSUE-008

Unity默认键位卡手问题

常见表现

游戏自带键位支持但存在一些问题,例如:WASD走不动路、按键无法长按、按键无法连点。

相关源码

Unity引擎 UnityView+Keyboard.mm

static const double kKeyTimeoutInSeconds = 0.5;

- (void)processKeyboard
{
    KeyMap& map = GetKeyMap();
    if (map.size() == 0)
        return;
    std::vector<int> keysToUnpress;
    double nowTime = GetTimeInSeconds();
    for (KeyMap::iterator item = map.begin();
         item != map.end();
         item++)
    {
        // Key has expired, register it for key up event
        if (nowTime - item->second > kKeyTimeoutInSeconds)
            keysToUnpress.push_back(item->first);
    }

    for (std::vector<int>::iterator item = keysToUnpress.begin();
         item != keysToUnpress.end();
         item++)
    {
        map.erase(*item);
        UnitySetKeyboardKeyState(*item, false);
    }
}

原因分析

早期的iOS系统并没有提供键盘输入的API,所以Unity尝试通过UIKeyCommand这种取巧的方式来实现。但UIKeyCommand只支持按键按下事件,并没有提供按键抬起事件。所以Unity又尝试通过“0.5秒后自动松开”来模拟按键抬起,也就造成了游戏过程中按键卡手的情况。

自iOS 14.0起已经新增了GCKeyboard这样的键盘输入API,但Unity引擎并没有随之更新它的代码。

解决方法

玩家方面:通过PlayCover的按键映射去覆盖默认键位。

开发者方面:使用GCKeyboard API重写UnityView+Keyboard.mm。

有一份现成的版本:gist,但这个版本不支持设备断开重连,通过GCKeyboardDidConnectNotification和GCKeyboardDidDisconnectNotification可以监听到设备断开重连。

ISSUE-009

虚幻引擎缺少Entitlement

常见表现

启动闪退,无崩溃报告。

通过终端运行游戏,日志停留在Mobile Provision not found。

相关源码

虚幻引擎 IOSPlatformMisc.cpp

void FIOSPlatformMisc::PlatformInit()
{
	//...
	
	// Check for required entitlements
	TArray<FString> RequiredEntitlements;
	GConfig->GetArray(TEXT("/Script/IOSRuntimeSettings.IOSRuntimeSettings"), TEXT("RequiredEntitlements"), RequiredEntitlements, GEngineIni);
	for (const FString& Entitlement : RequiredEntitlements)
	{
		if (!FIOSPlatformMisc::IsEntitlementEnabled(TCHAR_TO_ANSI(*Entitlement)))
		{
			UE_LOG(LogInit, Fatal, TEXT("App does not have required entitlement %s."), *Entitlement);
		}
	}
	
	//...
}

原因分析

虚幻引擎会检查是否有对应的Entitlement,如果没有的话,会触发UE_LOG(Fatal)直接闪退。

解决方法

虚幻引擎会先从可执行文件中读取Entitlement,然后尝试读取应用本体内的embedded.mobileprovision文件,所以伪造一个embedded.mobileprovision文件即可:

  • 打开第一个目录:右键游戏图标,选择“在访达中查看”,返回上一级目录,进入Entitlements。
  • 打开第二个目录:右键游戏图标,选择“在访达中查看”,右键选择“显示包内容”。
  • 将第一个目录中对应游戏的plist文件拷贝至第二个目录,重命名为embedded.mobileprovision。

ISSUE-010

Process Forked报错

常见表现

游戏运行时不停弹出崩溃报告,显示“multi-threaded process forked”。

原因分析

游戏在检测越狱环境。

解决方法

方法一:使用PlayCover Nightly版。

方法二:右键游戏图标 - 设置 - 绕过设置,启用“绕过越狱检测”选项。

ISSUE-011

查询可用运行内存的API返回错误结果

常见表现

游戏提示“设备性能不达标”。

游戏采用最保守的内存管理策略,导致渲染距离极低、材质质量极低。

原因分析

iOS有一个用于查询可用运行内存的函数os_proc_available_memory,该函数在Mac上可能会返回错误的结果,极端情况下该函数总是返回 0 。

解决方法

固定返回4个G的可用运行内存。

BUNDLE_ID=com.companyname.appname
BUNDLE_PATH=~/Library/Containers/io.playcover.PlayCover/Applications/$BUNDLE_ID.app
EXECUTABLE=$BUNDLE_PATH/$(/usr/libexec/PlistBuddy -c "Print :CFBundleExecutable" $BUNDLE_PATH/Info.plist)
FUNC_ADDR=$(otool -Iv "$EXECUTABLE" | grep _os_proc_available_memory | head -n1 | awk '{print $1}')
printf '\x20\x00\xC0\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR-0x100000000)) conv=notrunc
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

Tip

将指令中第一个字节\x20改为\x40,即可变为8个G。

ISSUE-012

我不好说

ISSUE-013

Unity游戏屏幕方向错误

常见表现

屏幕方向错误。

相关源码

Unity引擎 UnityAppController+ViewHandling.mm

- (UIViewController*)createRootViewController
{
    UIViewController* ret = nil;
    if (!UNITY_SUPPORT_ROTATION || UnityShouldAutorotate())
        ret = [self createUnityViewControllerDefault];

    if (ret == nil)
        ret = [self createRootViewControllerForOrientation: ConvertToIosScreenOrientation((ScreenOrientation)UnityRequestedScreenOrientation())];

    return ret;
}

原因分析

原因不明。

解决方法

方法一:尝试通过command+R旋转屏幕方向。

方法二:写入补丁,屏蔽源码中对createUnityViewControllerDefault的调用,createRootViewControllerForOrientation的传入参数修改为UIInterfaceOrientationLandscapeLeft (4)。

ISSUE-014

上层View导致按键映射失灵

常见表现

同时按下WASD和鼠标后(触发多点触控),按键映射失灵。

相关源码

UIKitCore.framework

void -[UIResponder touchesBegan:withEvent:] {
	forwardTouchMethod(self, SEL, touches, event, 0LL);
}

void forwardTouchMethod(UIResponder *responder, SEL selector, NSSet *touches, UIEvent *event, int flag) {
	UIResponder *nextResponder = responder.nextResponder;
	NSMutableSet *newTouches = [[NSMutableSet alloc] init];
	for (UITouch *touch in touches) {
		if (UIResponderForwarderWantsForwardingFromResponder(touch, selector, responder, nextResponder, event)) {
			[newTouches addObject: touch];
		}
	}
	if (newTouches.count > 0) {
		[nextResponder performSelector:selector with: newTouches, event];
	}
}

BOOL UIResponderForwarderWantsForwardingFromResponder(UITouch *touch, SEL selector, UIResponder *curResponder, UIResponder *nextResponder, UITouchesEvent *event) {
	// ...
	NSSet *touches = [event touchesForWindow:touch.window];
	if (touches.count > 1) {
		return NO;
	}
	// ...
}

PlayTools PTFakeMetaTouch.m

void eventSendCallback() {
    UIEvent *event = [[UIApplication sharedApplication] _touchesEvent];
    [event _clearTouches];
    
    [livingTouchAry enumerateObjectsUsingBlock:^(UITouch *aTouch, NSUInteger idx, BOOL *stop) {
        [event _addTouch:aTouch forDelayedDelivery:NO];
    }];

    [[UIApplication sharedApplication] sendEvent:event];
}

原因分析

Root View(UnityView)的上层存在另一个View(ARCoachingOverlayView),同时上层View的isUserInteractionEnabled属性为true,但没有重写touchesBegan:withEvent:。

PlayCover的按键映射代码,将多个UITouch放入一个UIEvent中,然后通过[UIApplication sendEvent:]发送事件。

首先上层View(ARCoachingOverlayView)接收到此事件,但因为其本身没有重写touchesBegan:withEvent:,所以交由基类UIResponder的touchesBegan:withEvent:来处理。

正常来说,UIResponder会将事件转发给下一个UIResponder(即UnityView)。

但UIResponderForwarderWantsForwardingFromResponder函数发现UIEvent包含多个UITouch,拒绝转发。

解决方法

方法一:阻止创建上层View。

方法二:将上层View的isUserInteractionEnabled属性改为false。

方法三(临时):修改PlayCover代码,确保UIEvent只包含一个UITouch。

PlayTools PTFakeMetaTouch.m

void eventSendCallback() {
    UIEvent *event = [[UIApplication sharedApplication] _touchesEvent];
    
    [livingTouchAry enumerateObjectsUsingBlock:^(UITouch *aTouch, NSUInteger idx, BOOL *stop) {
	    [event _clearTouches];
        [event _addTouch:aTouch forDelayedDelivery:NO];
	    [[UIApplication sharedApplication] sendEvent:event];
    }];
}

ISSUE-015

Game Center登录界面不显示

常见表现

游戏加载时卡住,游戏登录过程卡住。

原因分析

游戏与Game Center登录强绑定,需要等Game Center登录API -[GKLocalPlayer setAuthenticateHandler:]返回结果后才会继续下一步。

但由于签名限制,PlayCover中的应用是无法拉起Game Center登录界面的,Game Center登录API也不会有任何反应,甚至不会通过回调函数返回错误信息。

解决方法

方法一:禁用SIP并修改boot-args,可正常显示Game Center登录界面。

方法二:伪造一个用户已取消操作的Game Center登录结果。

PlayTools NSObject+Swizzle.m

#import <GameKit/GameKit.h>

- (void) hook_setAuthenticateHandler:(void (^)(UIViewController *, NSError *))handler {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        NSError *error = [NSError errorWithDomain:GKErrorDomain
                                             code:GKErrorCancelled
                                         userInfo:@{
            NSLocalizedDescriptionKey: @"The requested operation has been cancelled or disabled by the user."
        }];
        if (handler != nil) {
            handler(nil, error);
        }
    });
}

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.01 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
	[objc_getClass("GKLocalPlayer") swizzleInstanceMethod:@selector(setAuthenticateHandler:) withMethod:@selector(hook_setAuthenticateHandler:)];
});

ISSUE-016

腾讯游戏麦克风权限问题

常见表现

已授予麦克风权限,但游戏依旧提示没有权限。

相关源码

libGCloudVoice.a CProcessingGraph.o

bool ApolloTVE::CProcessingGraph::IsMicEnable() {
    bool bRet;
    if (this->m_bM1Process) { // Mac
         int64_t TimeMs = GetTimeMs();
         bool bWait = true;
         while (bWait) {
             if (GetTimeMs() - TimeMs > 100) {
                 bWait = false;
             }
             [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
                   bRet = granted;
                   bWait = false;
             }];
         }
    }
    else {
        [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
             bRet = granted;
        }];
    }
    return bRet;
}

原因分析

语音SDK在查询麦克风权限时,期望游戏处于暂停状态,并在暂停状态结束后立即获得查询结果。

但是通过PlayCover运行的游戏,查询麦克风权限时并不会被暂停,而是处于完全异步的状态。

解决方法

使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“checkMicPermissionSync”选项。

ISSUE-017

WebView界面打不了字

常见表现

启用按键映射的情况下,打不了字。

原因分析

与ISSUE-006类似,只不过出问题的地方变成WebKit的WKContentView了。

解决方法

临时解决方法:

右键游戏图标 - 设置 - 键盘映射设置,禁用“按键映射布局” 或 禁用“智能按键映射”。

临时修复代码:

PlayTools NSObject+Swizzle.m

手动发送相关事件广播。

- (BOOL)hook_WKContentView_becomeFirstResponder {
    BOOL ret = [self hook_WKContentView_becomeFirstResponder];
    [[NSNotificationCenter defaultCenter] postNotificationName:UITextFieldTextDidBeginEditingNotification
                                                        object:nil];
    return ret;
}

- (BOOL)hook_WKContentView_resignFirstResponder {
    BOOL ret = [self hook_WKContentView_resignFirstResponder];
    [[NSNotificationCenter defaultCenter] postNotificationName:UITextFieldTextDidEndEditingNotification
                                                        object:nil];
    return ret;
}

[objc_getClass("WKContentView") swizzleInstanceMethod:@selector(becomeFirstResponder) withMethod:@selector(hook_WKContentView_becomeFirstResponder)];
[objc_getClass("WKContentView") swizzleInstanceMethod:@selector(resignFirstResponder) withMethod:@selector(hook_WKContentView_resignFirstResponder)];

ISSUE-018

NeoX引擎文件路径错误

常见表现

启动闪退,无崩溃报告。

通过终端运行游戏,日志显示“neox.xml not exist!”。

原因分析

NeoX引擎给所有文件路径都加上了前缀/private,导致找不到文件。

解决方法

修改常量字符串/private为/

BUNDLE_ID=com.companyname.appname
BUNDLE_PATH=~/Library/Containers/io.playcover.PlayCover/Applications/$BUNDLE_ID.app
EXECUTABLE=$BUNDLE_PATH/$(/usr/libexec/PlistBuddy -c "Print :CFBundleExecutable" $BUNDLE_PATH/Info.plist)
perl -e 'open F, "+<:raw", $ARGV[0] or die $!; local $/; my $d = <F>; my $i = index($d, "\x00\x2F\x70\x72\x69\x76\x61\x74\x65\x00"); exit 1 if $i < 0; seek F, $i, 0; print F "\x00\x2F\x00\x00\x00\x00\x00\x00\x00\x00"; close F;' $EXECUTABLE
codesign -fs- $EXECUTABLE --deep --preserve-metadata=entitlements

ISSUE-019

UI界面屏幕方向错误

常见表现

屏幕方向错误。

原因分析

有两种情况:

  • 该界面本身只支持竖屏。
  • 该界面支持横屏,但是supportedInterfaceOrientations第一次返回的值仅包含竖屏。

Mac上运行的iOS应用受限于supportedInterfaceOrientations第一次返回的值,如果第一次返回的值里面不包含横屏,就永远无法切换成横屏显示,

解决方法

找出出问题的UIViewController,强制supportedInterfaceOrientations返回UIInterfaceOrientationMaskLandscape (24)。

ISSUE-020

我不好说

ISSUE-021

QTWebEngine界面加载问题

常见表现

登录界面报错,登录界面加载不出来。

游戏目录中存在Qt5WebEngineCore.dll文件。

原因分析

原因不明,与Chromium内核相关。

解决方法

在Wine容器中执行命令,添加环境变量QT_QUICK_BACKEND=software:

reg add "HKCU\Environment" /v QT_QUICK_BACKEND /t REG_SZ /d "software" /f

ISSUE-022

App跟踪询问窗口不显示

常见表现

加载卡住,登录卡住。

游戏提示接下来会弹出App跟踪询问窗口,但没有出现任何界面。

相关源码

PlayTools PlayShadow.m

+ (void) load {
    //...
    [objc_getClass("ATTrackingManager") swizzleClassMethod:@selector(requestTrackingAuthorizationWithCompletionHandler:) withMethod:@selector(pm_return_2_with_completion_handler:)];
    [objc_getClass("ATTrackingManager") swizzleClassMethod:@selector(trackingAuthorizationStatus) withMethod:@selector(pm_return_2)];
    //...
}

原因分析

游戏请求弹出App跟踪询问窗口,等待窗口关闭后才会继续下一步加载或登录操作。但是在Mac上运行的iOS应用是不会弹出这个窗口的,所以应用会一直等待结果,故而卡住了。

如上面的源码所示,其实PlayCover早已对这个问题做了处理。但是在运行某些游戏时,由于AppTrackingTransparency.framework加载得太慢,源码中的objc_getClass("ATTrackingManager")为nil,导致这个处理被跳过了。

解决方法

方法一:修改PlayCover代码,提前加载AppTrackingTransparency.framework。

方法二:写入补丁,让游戏跳过App跟踪这个步骤。

ISSUE-023

CRIWARE多线程死锁问题

常见表现

加载过程中卡死,程序转圈无响应。

原因分析

CRIWARE启用SonicSYNC后出问题。

解决方法

初始化CRIWARE时不要启用SonicSYNC。

方法一:修改resources.assets中的CriWareIntializer(仅适用于Unity游戏)。

  1. 使用UABEA打开resources.assets。
  2. Filter只保留MonoBehaviour,找到CriWareIntializer。
  3. 选择Export Raw。
  4. 打开UABEA导出的文件,修改iosEnableSonicSync为false,即\x01\x00\x00\x00修改为\x00\x00\x00\x00。但是对于不同版本的CriWare插件,数据位置可能不一样。以圆哆啦为例,数据位置在0xDC,所以可以在0xDC往前往后4个字节查找\x01\x00\x00\x00,逐一尝试替换。
  5. 选择Import Raw。
  6. 保存resources.assets。

方法二:写入二进制补丁。

查找字符串The linked library version is more recent than CRI Atom Ex header version,所在函数即为criAtomEx_global.o的criAtomEx_CalculateWorkSizeInternal函数,其中thread_model控制是否启用SonicSYNC。

typedef struct CriAtomExConfigTag {
	int thread_model;
	// ...
} CriAtomExConfig;

typedef struct CriAtomExConfigTag_IOS {
	CriAtomExConfig         atom_ex;
	CriAtomExAsrConfig      asr;
	CriAtomExHcaMxConfig    hca_mx;
	// ...
} CriAtomExConfig_IOS;

int criAtomEx_CalculateWorkSizeInternal(CriAtomExConfig_IOS *config, void *a2) {
	if (config) {
		// 必定进入此分支
		// ...
	} else {
		// ...
	}
}

把 if 判断的CBZ指令改成STR WZR, [X0],即可将thread_model改为0,从而不启用SonicSYNC。

ISSUE-024

Unity KeyboardDelegate初始化报错

常见表现

启动闪退。

通过终端运行游戏,日志显示“[KeyboardDelegate Initialize] called after creating keyboard”。

相关源码

Unity引擎 Keyboard.mm

@implementation KeyboardDelegate

+ (void)Initialize
{
    NSAssert(_keyboard == nil, @"[KeyboardDelegate Initialize] called after creating keyboard");
    if (!_keyboard)
        _keyboard = [[KeyboardDelegate alloc] init];
}

+ (KeyboardDelegate*)Instance
{
    if (!_keyboard)
        _keyboard = [[KeyboardDelegate alloc] init];

    return _keyboard;
}

@end

原因分析

游戏先调用了[KeyboardDelegate Instance],后调用[KeyboardDelegate Initialize],触发断言失败。

解决方法

方法一: 使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“ignoreUnityKeyboardInitializationError”选项。

方法二: 通过补丁屏蔽+[KeyboardDelegate Initialize]。

BUNDLE_ID=com.companyname.appname
EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/$BUNDLE_ID.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/KeyboardDelegate/{found=1} found && /Initialize/{f=1} f && /imp/{print $2; exit}')
printf '\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE

ISSUE-025

灵犀互娱SDK网页显示问题

常见表现

登录界面、公告界面的网页不显示。

相关源码

var isIOS = /iPad|iPhone|iPod/i.test(navigator.platform) ||
    (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);

原因分析

灵犀互娱SDK通过上面的代码来判断设备是否iOS,如果不是,则不会执行后续代码。

而在Mac上运行的iOS应用,打开网页时默认会请求桌面版网页,这种情况下navigator.platform = "MacIntel",但navigator.maxTouchPoints = 0,不满足上述代码中的条件判断。

解决方法

方法一:修改PlayCover代码,强制请求移动端网页,这种情况下navigator.platform = "iPad"。

PlayTools NSObject+Swizzle.m

#import <WebKit/WebKit.h>

- (WKWebView *) hook_WKWebView_initWithFrame:(CGRect) frame
                               configuration:(WKWebViewConfiguration *) config {
    WKWebView *webView = [self hook_WKWebView_initWithFrame:frame configuration:config];
    webView.configuration.defaultWebpagePreferences.preferredContentMode = WKContentModeMobile;
    return webView;
}

[objc_getClass("WKWebView") swizzleInstanceMethod:@selector(initWithFrame:configuration:) withMethod:@selector(hook_WKWebView_initWithFrame:configuration:)];

方法二:在应用数据中查找是否有缓存的网页文件,移除navigator.maxTouchPoints > 1这个条件判断。

ISSUE-026

libzmq.dll发送数据时无响应

原因分析

使用ZMQ时,TCP发送数据的缓冲区大小至少要有1MB。

参考:https://github.com/zeromq/libzmq/issues/2638

解决方法

查看当前的TCP缓冲区大小:

sysctl net.inet.tcp.sendspace

修改TCP缓冲区大小为1MB:

sudo sysctl net.inet.tcp.sendspace=1048576

ISSUE-027

MCMeta.plist文件不存在导致闪退

常见表现

启动闪退。

原因分析

一些SDK会读取/var/mobile/Library/UserConfigurationProfiles/PublicInfo/MCMeta.plist的文件时间,读取失败时会触发闪退。

但是只有iOS才有MCMeta.plist,macOS上并不存在这个文件。

解决方法

创建一个空文件即可:

sudo mkdir -p /var/mobile/Library/UserConfigurationProfiles/PublicInfo
sudo touch /var/mobile/Library/UserConfigurationProfiles/PublicInfo/MCMeta.plist

ISSUE-028

MarketplaceKit.framework不存在导致闪退

常见表现

启动闪退。

相关源码

import MarketplaceKit

func getDistributorName() async -> String {
	if #available(iOS 17.4, *) {
		let currentDistributor = try await AppDistributor.current
		switch currentDistributor {
		case .appStore:
			return "App Store"
		case .testFlight:
			return "TestFlight"
		case .marketplace(let bundleId):
			return "Alternative marketplace (\(bundleId))"
		case .web:
			return "Website"
		case .other:
			return "Other"
		default:
			return "Unknown"
		}
	} else {
		return "Unknown"
	}
}

原因分析

MarketplaceKit 只支持iOS,在macOS上调用此API时会因为找不到对应Framework而闪退。

解决方法

开发者方面:
通过ProcessInfo.processInfo.isiOSAppOnMac是否Mac平台,跳过相关API调用。

玩家方面:
方法一:通过二进制补丁跳到 if #available(iOS 17.4, *) 的另一个分支。
方法二:编译一个空实现的MarketplaceKit.framework,通过install_name_tool替换动态库路径。

ISSUE-029

Declared Age Range导致游戏卡住

常见表现

用户协议界面卡住,登录界面卡住。

活动监视器中出现 FamilyOutOfProcessUIExtension 进程。

相关源码

import DeclaredAgeRange

func isEligibleForAgeFeatures() async -> Bool {
	if #available(iOS 26.2, *) {
	    return (try? await AgeRangeService.shared.isEligibleForAgeFeatures) ?? false
	} else {
	    return false
	}
}

func requestAgeRange() async {
	if #available(iOS 26.2, *) {
		guard let response = try? await AgeRangeService.shared.requestAgeRange(
	        ageGates: 13, 15, 18, in: viewController) else {
	        return
	    }
	    // ...
	} else {
		// ...
	}
}

原因分析

应用在登录流程中尝试通过 Declared Age Range 查询用户的年龄范围。

但由于签名限制,PlayCover中的应用无法拉起年龄范围询问窗口,Declared Age Range API也不会有任何响应,甚至不会返回错误信息。

解决方法

方法一:打开活动监视器,尝试杀掉 FamilyOutOfProcessUIExtension 进程。

方法二:通过二进制补丁跳到 if #available(iOS 26.2, *) 的另一个分支。

方法三:编译一个空实现的DeclaredAgeRange.framework,通过install_name_tool替换动态库路径。

教程

PlayCover映射技能轮盘

  1. 在映射编辑模式中,点击轮盘按钮所在位置。

  2. 选择左下角鼠标图案的按钮,创建一个Mouse映射。

  3. 按下键盘上的任意键,以Tab键为例。

  4. 退出映射编辑模式,按住Tab键触发轮盘,此时挪动鼠标可以调整选中项。

    Note

    手柄方面暂不支持映射技能轮盘。

PlayCover映射方案切换

映射方案切换是PlayCover Nightly版新增的功能,PlayCover稳定版不支持。

  1. 右键游戏图标,选择playapp.keymap。


  2. 点击playapp.emptyKm,新建一个映射方案。


  3. 输入映射方案的名字。


  4. 右键菜单支持更多操作。


  5. 运行游戏后,通过快捷键 command + [ 或 command + ] 切换映射方案。


  6. 启动游戏后会先使用默认方案:

    按下 command + ] 切换方案,屏幕中央提示“Switched to next keymap”。

    为新方案设置映射:

PlayCover Nightly版翻译补全

PlayCover Nightly版作为早期测试版本,很多文本都还未完成翻译,但我们可以自己翻译并替换文件。

  1. 打开访达,在应用程序中找到PlayCover,右键显示包内容

  2. 进入Contents/Resources/zh-Hans.lproj

  3. 下载Localizable.strings进行替换

  4. 进入Contents/Frameworks/PlayTools.framework/Resources/zh-Hans.lproj

  5. 下载Playtools.strings进行替换


Tip

strings文件可以用文本编辑工具打开进行编辑。

Sideloadly添加支持全屏分辨率

通过Sideloadly安装的iOS应用,大部分是按照iPad的长宽比来显示的。通过修改Info.plist文件,可以将长宽比调整为与显示器保持一致。

→

操作步骤:

  1. 重命名ipa文件,添加 .zip 后缀,解压得到 Payload 文件夹。

  2. 进入 Payload 文件夹,右键游戏本体,选择显示包内容。

  3. 使用文本编辑打开 Info.plist 。

  4. 在最后一个</dict>的前面,添加<key>UISupportsTrueScreenSizeOnMac</key><true/>

    修改前:


    修改后:

  5. 保存Info.plist。

  6. 压缩 Payload 文件夹得到 Payload.zip,重命名为 .ipa 。

  7. 使用Sideloadly安装修改过的ipa文件即可。


参考文档:Apple Developer Documentation

虚幻引擎ini配置修改

如何找到ini配置目录

右键游戏图标 - 设置 - 详细信息,其中的“可执行文件名称”通常是项目名ProjectName。
右键游戏图标,显示应用数据,ini配置会在以下两个目录之中:

  • Data/Documents/{ProjectName}/Saved/Config/IOS
  • Data/Library/{ProjectName}/Saved/Config/IOS

修改分辨率缩放

PlayCover图像设置中的“分辨率缩放”选项对于虚幻引擎是不生效的,因为虚幻引擎为不同的机型预先配置了缩放系数,我们需要通过修改ini配置来调整。

打开DeviceProfiles.ini,添加以下内容:

[iPadPro7_129 DeviceProfile]
CVars=r.MobileContentScaleFactor=1.0

其中iPadPro7_129是机型代号。通过终端运行游戏,在日志中能找到这个机型代号:

常见的机型代号:

  • iPad Pro M1:iPadPro5_129
  • iPad Pro M2:iPadPro6_129
  • iPad Pro M4:iPadPro7_129,iPadPro7_13

修改全局UI缩放

打开Engine.ini,添加以下内容:
其中Time=1080表示分辨率高度1080,Value=0.7表示缩放值0.7。

[/Script/Engine.UserInterfaceSettings]
UIScaleRule=ShortestSide
UIScaleCurve=(EditorCurveData=(Keys=((Time=1080.000000,Value=0.70000000)),PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant,DefaultValue=0),ExternalCurve=None)

也可以为两种分辨率分别配置缩放值:

[/Script/Engine.UserInterfaceSettings]
UIScaleRule=ShortestSide
UIScaleCurve=(EditorCurveData=(Keys=((Time=1080.000000,Value=0.70000000),(Time=1440.000000,Value=0.90000000)),PreInfinityExtrap=RCCE_Constant,PostInfinityExtrap=RCCE_Constant,DefaultValue=0),ExternalCurve=None)

隐藏虚拟摇杆

打开Input.ini,添加以下内容:

[/Script/Engine.InputSettings]
DefaultTouchInterface=None

(主要对虚幻4游戏有效)

decrypt.day如何申请砸壳

登录网站

点击网站右上角的Login按钮进入登录页面。

如果手上没有这两种帐号,可以尝试用谷歌邮箱或Outlook邮箱去注册一个Discord帐号。注册Discord帐号时可能会遇到封号的情况,请自行解决。

获取App Store链接

申请砸壳需要提供应用的App Store链接。

1. 如果站内已经存在这个应用

  • 在STORE Link的位置上右键选择“拷贝链接”即可。

2. 如果站内还没有这个应用

  • 在浏览器中打开 https://apps.apple.com
    (目前会强制跳转国区商店,如果需要查询外区App,请开启全局代理)

  • 在页面底部点击 United States

  • 选择对应的地区

  • 搜索应用,点击”查看“

  • 拷贝地址栏中的链接

    Tip

    除此之外,还可以通过以下方法获取:

    • 在搜索引擎中搜索“游戏名 地区名 appstore”,例如“金铲铲之战 cn appstore”。
    • 直接向 AI 询问。

申请砸壳

在decrypt.day网站中点击Request Decrypt:



填入应用的App Store链接:

MaaTools独立插件

下载地址

https://github.com/viatearz/MaaTools/releases

使用方法

解压zip文件后,进入目录:

cd MaaTools

安装MaaTools:

sh maatools.sh install <Bundle ID>

卸载MaaTools:

sh maatools.sh uninstall <Bundle ID>

列出所有应用的MaaTools安装状态:

sh maatools.sh list

Tip

在PlayCover界面右键游戏图标,选择 设置 ,在详细信息中可查看应用的Bundle ID。

或者可以通过上述的 sh maatools.sh list 命令去查看。

配置修改

在PlayCover界面右键游戏图标,选择 在访达中查看 ,找到 .maa.json 结尾的配置文件。

{
	"enabled": 1,   // 是否启用MaaTools:1-启用,0-不启用
	"port": 1717,   // 通信端口
	"debug": 0      // 是否启用调试(可视化触摸操作):1-启用,0-不启用
}

常见问题

1. 是否会和已内置MaaTools的PlayCover版本冲突?

不会。如果在PlayCover 绕过 设置中打开了 MaaTools 选项,那么会优先运行内置版本的MaaTools,独立版本的MaaTools将不会运行。

2. 重新安装IPA后,需要重新安装MaaTools吗?

需要。

3. 如何更新升级MaaTools?

只需要对任意一个应用重新执行一次安装指令即可,或者你可以手动将MaaTools.framework拷贝至~/Library/Frameworks。

MaaGakumasu

使用方法

  1. 使用PlayCover Nightly版安装学园偶像大师,分辨率设置选择settings.picker.adaptiveRes.6(自由缩放),长宽比选择settings.picker.aspectRatio.free(自由)。

  2. 安装 MaaTools :

    sh maatools.sh install jp.co.bandainamcoent.BNEI0421
    
  3. 下载 MaaGakumasu-macos-aarch64.zip。

  4. 解压文件后,执行终端指令:

    cd ~/Downloads/MaaGakumasu-macos-aarch64-v1
    xattr -dr com.apple.quarantine .
    chmod a+x MFAAvalonia
    chmod a+x python/bin/python3
    
  5. 下载定制修改过的 MaaPlayCoverControlUnit:
    打开 GitHub Actions ,选择第一个 build-playcover-control-unit ,在页面底部下载 MaaPlayCoverControlUnit 文件(需要登录GitHub账号)。

  6. 解压文件后,执行终端指令:

    xattr -dr com.apple.quarantine ~/Downloads/MaaPlayCoverControlUnit
    
  7. 将MaaPlayCoverControlUnit/MaaGakumasu/libMaaPlayCoverControlUnit.dylib拷贝至MaaGakumasu-macos-aarch64-v1/runtimes/osx-arm64/native进行替换。

  8. 打开MaaGakumasu-macos-aarch64-v1目录,双击运行MFAAvalonia。

  9. 在MaaGakumasu中选择PlayCover控制器,点击右侧的笔图标,地址填入 localhost:1717。

注意事项

  1. 执行自动培育之前,请先前往主页-设置-プロデュース,打开所有“跳过“的选项,关闭所有“二次确认“的选项。

版本说明

原版MAA只支持单一的截图分辨率,并不支持横竖屏切换,所以这里需要使用修改过的MaaTools和MaaPlayCoverControlUnit。

不替换MaaPlayCoverControlUnit也是可以运行的,但是当自动培育到达Live阶段时,会因为横屏截图出错而卡住。

PlayCover修改版

该版本兼容官方的Nightly版,可随时换回Nightly版。

下载地址

GitHub

点击第一个Build unsigned release,在页面底部下载dmg安装包(需要登录GitHub账号):

https://github.com/viatearz/PlayCover/actions/workflows/unsigned_release.yml

123云盘

https://www.123912.com/s/nPGwTd-9QJb

常见问题

1. “PlayCover”已损坏

解决方法:按下command + 空格键,输入“终端”。复制以下指令,按回车执行。

xattr -dr com.apple.quarantine /Applications/PlayCover.app

2. 切换到修改版后并未解决问题

请尝试以下重置操作:

  • 右键游戏图标 - 设置 - 重置设定。
  • 重新安装一次IPA。

更新日志

v61:
怪物猎人:旅人(国际服):修复启动报错。
NIKKE(国际服):修复音游小游戏不显示键位设置的问题。

v60:
绿梦:时空之声:修复启动闪退。

v55:
糖豆人:修复启动闪退。

v54:
战争雷霆手游:修复启动闪退。

v52:
诡秘之主:修复启动闪退。
金铲铲之战:修复阵容推荐显示问题(需重置设定)。
eFootball™ / 实况足球:修复登录后无限Loading的问题。

v51:
云·终末地:修复按键映射与云游戏的兼容问题。
云·异环:修复按键映射与云游戏的兼容问题。

v50:
NIKKE(国际服):修复音游小游戏不显示键位设置的问题。

v49:
Warframe:修复恢复开启SIP后登录状态丢失的问题。
光·遇(国际服):修复登录问题。
其他:修复macOS 27 beta5 打不开游戏的问题。

v48:
Heaven Burns Red(国际服):修复认证失败报错。

v47:
云·鸣潮:取消移动鼠标至屏幕中央,防止镜头乱飘。
Minecraft(国际版):新增优化鼠标滚轮的可选设置。
我的世界(国服):修复键鼠问题。
无职转生 回响编年史:修复登录报错(需清除数据、重启电脑)。
其他:修复第二次打开PlayCover时变成3.1.0正式版的bug。

v46:
云·原神:修复提示“参数错误”的问题。
云·星穹铁道:修复提示“参数错误”的问题。
云·鸣潮:支持鼠标自动显示隐藏,支持滚轮缩放。
云·异环:修复鼠标点击没反应的问题。
云·终末地:修复鼠标点击没反应的问题。
云·二重螺旋:修复鼠标点击没反应的问题。

v45:
地下城与勇士:起源:游戏已修复内置键盘,调整设置项(设置-额外设置-取消禁用内置键盘)。

v44:
Minecraft(国际版):修复打不了字的bug。

v43:
Minecraft(国际版):修复登录及键鼠问题。
失控进化:修复闪退问题。

v42:
七大罪:Origin:修复自带鼠标适配失效的问题。

v41:
舞力全开:派对:修复启动闪退。

v40:
时空猎人·觉醒:修复启动卡死问题。
Facebook Messenger:修复登录闪退。

v39:
地下城与勇士:起源:修复启动闪退;修复键盘没反应的问题。
闪电十一人 Cross:绕过反作弊闪退。

v37:
其他:修复自定义鼠标光标在macOS 26上闪退的问题。

v36:
夜幕之下:修复启动闪退。
欢乐斗地主:修复启动闪退。

v35:
向僵尸开炮:修复启动闪退。
黑子的篮球 街头对决:修复启动闪退。
三国志异闻录:修复启动闪退。
燕云十六声:修复切换界面时长时间黑屏的问题。

v34:
植物大战僵尸2:修复屏幕方向错误的问题。
游戏王 决斗链接(国际服):修复账号连携问题(需使用Chrome浏览器)。

v33:
彩虹六号M:修复登录界面闪退(可能还存在其他闪退问题)。
其他:拖拽按钮映射支持手柄瞄准模式。

v32:
NIKKE(国际服):修复音游小游戏不显示键位设置的问题。

v31:
战双帕弥什:修复启动闪退。
猫咪大战争(日服):修复启动闪退。
糖豆人:修复登录失败的问题。

v30:
乱涂!彩世界:修复启动闪退。
战舰世界:传奇:修复启动闪退。
其他:新增iPad Pro M5机型选项。

v29:
NIKKE(国际服):修复音游小游戏的键盘操作问题。

v27:
其他:优化偶尔不显示自定义鼠标光标的问题。

v25:
其他:修复按键映射菜单功能错位的问题(上游代码bug)。

v23:
魔御:STAR DIVE:禁用自带键盘处理。
荒野大镖客 iOS版:修复安装闪退问题;绕过扩展资源下载(需另外从网盘下载数据包)。
其他:拖拽按钮映射支持使用鼠标右键作为触发键。

v22:
全境封锁:曙光:修复启动闪退;修复键鼠适配问题。

v21:
七大罪:Origin:修复键鼠适配问题。

v19:
DISSIDIA DUELLUM FINAL FANTASY:修复启动闪退。

v17:
洛克王国:世界:修复安装闪退问题。

v16:
VAMPIR:血之继承者:消除键盘按键嘟嘟声。

v1-v15:
初期测试版本。

功能说明

1. 自定义鼠标光标

鼠标图片下载:https://www.123912.com/s/nPGwTd-oHJb (123云盘)

2. 拖拽操作优化

基础使用教程: 点击查看

在原先的基础上新增了几个模式,同时支持鼠标右键作为触发键。

模式说明:

  • 键鼠·模式一:鼠标隐藏。
  • 键鼠·模式二:鼠标会显示在屏幕正中央,和PC端的轮盘逻辑一致。
  • 手柄·模式一:瞄准模式,松开触发键时确认操作。
  • 手柄·模式二:轮盘模式,松开摇杆时确认操作。