🎮 Mac Mobile Gaming Tutorials
欢迎来到本网站!
这里专注于整理与分析在 macOS 上运行手机游戏的常见问题及对应解决方案。
网站内容
常用工具
| 图标 | 工具 | 说明 |
|---|---|---|
![]() | PlayCover | 可安装iOS游戏,原生运行无损耗。支持分辨率调整、按键映射等功能。 |
![]() | PlayCover Nightly | PlayCover的早期测试版本,包含新的功能、新的修复以及对最新macOS的适配。 |
![]() | Sideloadly | 可安装iOS游戏,原生运行无损耗。使用免费证书签名时,每7天需要重新安装一次。 |
![]() | CrossOver | 可安装Windows游戏。 支持 最新Wine + D3DMetal / DXMT |
![]() | CrossOver Preview | CrossOver的预览测试版本,包含新的功能、新的修复以及最新版本的Wine。 |
![]() | Sikarugir | 可安装Windows游戏。 支持 旧版Wine + D3DMetal / DXMT |
![]() | Heroic Games Launcher | 可安装Windows游戏。 支持 旧版Wine + D3DMetal、最新Wine + DXMT |
![]() | BlueStacks Air | 安卓模拟器。 |
![]() | MuMu模拟器 Pro | 安卓模拟器。收费。 |
IPA资源站点
| 图标 | 站点 | 说明 |
|---|---|---|
![]() | https://decrypt.day | 可免费下载IPA。 免费链接会在下载一定次数后失效,建议在游戏版本更新当天尽快下载。 |
![]() | https://armconverter.com | 可免费下载美区IPA,其他区收费。 |
![]() | https://ipa.store | 可免费下载国区和美区IPA,使用国内网盘。 |
注意事项
- 随着游戏版本更新,指令可能会失效。大多数情况下重装游戏即可还原指令的改动。
- 指令以国服为主,其他服务器版本可能需要自行替换Bundle ID。
- 如有意愿制作详细版教程,可随意使用本站的内容。
新游概况
| 游戏名 | 上线时间 | 引擎 | App Store | PlayCover Sideloadly | CrossOver Wine | 备注 |
|---|---|---|---|---|---|---|
| 约会大作战: Love Limit Break | 26/03/17 | Unity | ✅ | |||
| 七大罪:Origin | 26/03/17 | UE5 | ❓ | ❌ | ||
| VAMPIR:血之继承者 | 26/03/11 | UE5 | ✅ | ✅ | ||
| 我推的孩子 Puzzle Star | 26/02/25 | Unity | ✅ | |||
| 彩虹六号M | 26/02/24 | Unity | ❌ | |||
| 铁扣嘉年华 (テクロノス) | 26/02/19 | Unity | ✅ | |||
| HUNTER×HUNTER NEN×SURVIVOR | 26/02/18 | Unity | ❌ | |||
| 魔法少女小圆 Magia Exedra (台服) | 26/02/10 | Unity | ❌ | ✅ | ||
| 吉星派对 | 26/02/06 | Unity | ✅ | ✅ | ✅ | |
| 天界地狱 (헤븐헬즈) | 26/02/04 | Unity | ✅ | ✅ | App Store下载需要认证满19岁 | |
| 少女前线:火力控制 (东南亚服) | 26/01/29 | Unity | ✅ | |||
| 汉克旅店 | 26/01/28 | Unity | ✅ | |||
| 明日方舟:终末地 | 26/01/22 | Unity | ✅ | ❌ | ||
| 龙之剑 (드래곤소드) | 26/01/21 | UE5 | ❌ | ❌ | ||
| 蔚蓝档案PC版 (日服) | 26/01/20 | Unity | ✅ | |||
| 空灵诗篇 (国服) | 26/01/15 | Unity | ✅ | ✅ | ||
| 逆战:未来 | 26/01/13 | UE4 | ✅ | ❌ | ||
| 风之痕迹 | 26/01/08 | Unity | ❌ | ✅ | ✅ |
游戏列表
- 堡垒之夜
- 碧蓝航线
- 边狱巴士
- 蛋仔派对
- 第五人格
- 巅峰极速
- 二重螺旋
- 幻塔
- 火炬之光:无限
- 金铲铲之战
- 开放空间
- 恋与深空
- 锚点降临
- 鸣潮
- 明日方舟:终末地
- 命运:群星
- 魔法少女小圆Magia Exedra
- 逆战:未来
- 女神异闻录:夜幕魅影
- 七大罪:光与暗之交战
- 七骑士 Re:BIRTH
- 三国志·战略版
- 少女前线2:追放
- 失落之剑
- 实况足球(eFootball)
- 天涯明月刀手游
- 蔚蓝档案
- 星塔旅人
- 学园偶像大师
- 永恒之塔2
- 棕色尘埃2
- 最终幻想14:水晶世界
- NIKKE
堡垒之夜
PlayCover
1. 启动闪退 ISSUE-009
打开第一个目录:右键游戏图标,选择“在访达中查看”,返回上一级目录,进入Entitlements。
打开第二个目录:右键游戏图标,选择“在访达中查看”,右键选择“显示包内容”。
将第一个目录中的com.epicgames.FortniteGame.plist拷贝至第二个目录,重命名为embedded.mobileprovision。
2. 启动闪退2 ISSUE-011
通过终端指令修复:
EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.epicgames.FortniteGame.app/FortniteClient-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 -rf /Users/$USER/Library/Containers/com.epicgames.FortniteGame/Data/Documents/Users/$USER/Library/Containers/com.epicgames.FortniteGame/Data && ln -sf /Users/$USER/Library/Containers/com.epicgames.FortniteGame/Data /Users/$USER/Library/Containers/com.epicgames.FortniteGame/Data/Documents/Users/$USER/Library/Containers/com.epicgames.FortniteGame/Data
碧蓝航线
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
2. 摇杆映射问题 ISSUE-007
使用PlayCover Nightly版,在编辑模式中选中WASD控件,更改为自由摇杆模式。
第五人格
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
2. 摇杆映射问题 ISSUE-007
使用PlayCover Nightly版,在编辑模式中选中WASD控件,更改为自由摇杆模式。
巅峰极速
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
国际服
rm -r /Users/$USER/Library/Containers/com.panstudio.duetnightabyss.arpg.global/Data/Library/Users/$USER/Library/Containers/com.panstudio.duetnightabyss.arpg.global/Data && ln -sf /Users/$USER/Library/Containers/com.panstudio.duetnightabyss.arpg.global/Data /Users/$USER/Library/Containers/com.panstudio.duetnightabyss.arpg.global/Data/Library/Users/$USER/Library/Containers/com.panstudio.duetnightabyss.arpg.global/Data
2. 鼠标点击异常 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
因反作弊无法运行。
幻塔
App Store
Mac原生版本,非高配芯片不建议尝试。
PlayCover
1. 游戏跳过更新资源直接到达登录界面 ISSUE-001
PlayCover Nightly版已修复此问题。
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. 鼠标点击异常 ISSUE-003
使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。
金铲铲之战
PlayCover
1. 麦克风权限问题
游戏提示“您拒绝了麦克风权限,请在MacOS系统设置,隐私和安全设置当中手动打开金铲铲之战麦克风权限”。
原因分析
游戏通过UnityEngine.Application.HasUserAuthorization(UserAuthorization.Microphone)查询麦克风权限。不过经过逆向分析,此接口返回的结果总是false。推测是因为游戏打包时未设置Preprocessor.h中的宏定义UNITY_USES_MICROPHONE,导致并没有包含麦克风权限处理的相应代码。
写入补丁,强制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/MSDKWebView.framework/MSDKWebView
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/MSDKBaseWebViewController/{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
临时解决办法:右键游戏图标 - 设置 - 键盘映射设置,禁用“智能按键映射”。
开放空间
App Store
有上架iOS版。
商店页面显示“未针对macOS验证”,即开发者并未对Mac进行适配。
-
键盘只支持WASD移动,其余键位不支持。
-
存在CPU占用异常偏高的问题。
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版,右键游戏图标 - 设置 - 图像设置,分辨率选择“settings.picker.adaptiveRes.6(Resizable)”。
2. 登录界面打不了字
右键游戏图标 - 设置 - 键盘映射设置,禁用“按键映射布局”。
登录完成后再重新打开这个选项。
3. 切换横屏
保存下面的脚本代码至文件lysk.scpt,在终端中运行osascript lysk.scpt可以快速调整至横屏。
脚本中的 w 是窗口宽度,h 是窗口高度,窗口的长宽比要和显示器的保持一致。
tell application "Finder"
set screenBounds to bounds of window of desktop
set screenWidth to item 3 of screenBounds
set screenHeight to item 4 of screenBounds
end tell
tell application "System Events"
tell process "恋与深空"
set w to 1280
set h to 800
set x to (screenWidth - w) / 2
set y to (screenHeight - h) / 2
set position of window 1 to {x, y}
set size of window 1 to {w, h}
end tell
end tell
tell application "恋与深空" to activate
delay 0.1
tell application "System Events"
keystroke "k" using command down
delay 0.1
keystroke "k" using command down
delay 0.1
keystroke "a" using option down
end tell
Note
如果提示找不到“恋与深空“,请改成“com.papegames.lysk“。
Note
如果提示没有操作权限,请打开系统设置 - 隐私与安全性,授予”终端“辅助功能和自动化的权限。
锚点降临
App Store
加载卡住,无法游玩。
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
Important
如果之前安装过iOS版,请先清除应用数据缓存以避免冲突:
点击访达菜单 - 前往 - 前往文件夹 - 输入~/Library/Containers/鸣潮,删除此文件夹。
Mac原生版本,可正常游玩。
PlayCover
Important
如果之前安装过Mac版,请先清除应用数据缓存以避免冲突:
右键游戏图标,选择“显示应用数据”,删除“鸣潮”文件夹。
1. 中文系统下启动游戏闪退 ISSUE-002
PlayCover Nightly版已修复此问题。
2. 文件重命名失败报错 ISSUE-001
PlayCover Nightly版已修复此问题。
3. 登录界面点击会自动关闭 ISSUE-003
使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。
4. 资源更新界面点不了下载 ISSUE-003
使用PlayCover Nightly版,右键游戏图标 - 设置 - 键盘映射设置,启用“disableBuiltinMouse”选项。
5. 键鼠用不了快捷轮盘
当然,键鼠玩家还是推荐用Mac版。
6. 键鼠开不了摩托车
当然,键鼠玩家还是推荐用Mac版。
目前游戏已支持通过摇杆操控摩托车。
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. 运行帧率低/发热严重
右键游戏图标,选择“显示应用数据”,进入鸣潮/Data/Library/Client/Saved/Config/IOS,用文本编辑打开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
可任意修改等号后面的数值。数值越小,画面越糊,运行越流畅,发热越少。
明日方舟:终末地
PlayCover
1. 短暂运行后闪退 ISSUE-012
使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“blockSleepSpamming”选项。
2. 神秘弹窗
PlayCover Nightly版已修复此问题。
CrossOver
因反作弊无法运行。
命运:群星
👍 极其少有的对iOS版做了完整键鼠适配的游戏。
PlayCover
- 手柄方面正常。
- 键鼠方面因为PlayCover的代码默认会拦截隐藏鼠标指针的操作,导致游戏自带的键鼠适配无法正常工作。
Sideloadly
完美运行。
魔法少女小圆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. 播放剧情动画提示“网络错误”
临时解决方法:使用其他设备观看。
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
逆战:未来
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
不支持运行WeGame,因反作弊无法运行。
女神异闻录:夜幕魅影
PlayCover
1. 国服启动闪退 ISSUE-024
通过终端指令修复:
EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.pwrd.persona5x.pw.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
2. 国际服弹出错误报告 ISSUE-010
解决方法一:使用PlayCover Nightly版,默认已修复此问题。
解决方法二:右键游戏图标 - 设置 - 绕过设置,启用“绕过越狱检测”选项。
3. CPU占用异常偏高 ISSUE-004
使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。
CrossOver
国服版本因反作弊无法运行。
七大罪:光与暗之交战
PlayCover
1. 画面显示不全
使用PlayCover Nightly版,右键游戏图标 - 设置 - 图像设置,分辨率选择“settings.picker.adaptiveRes.6(Resizable)”。
2. 无限Loading ISSUE-015
通过终端指令修复:
修改-[NMGGameCenterManager returnCallbackOrRegisterAuthenticateHandler:],跳过Game Center Login步骤。
EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.netmarble.nanagb.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/NMGGameCenterManager/{found=1} found && /baseMethods/{f=1; i=0} f && /imp/{i++; if(i==28){print substr($3,2,length($3)-2); exit}}')
printf '\xB5' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR+0x9B)) conv=notrunc
codesign -fs- $EXECUTABLE
CrossOver
正常运行。
添加命令行参数--in-process-gpu可打开Netmarble Launcher。
七骑士 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的条件判断。
少女前线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. 无限Loading ISSUE-022
通过终端指令修复:
EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.wemadeconnect.ios.lostdgl.app/Frameworks/UnityFramework.framework/UnityFramework
FUNC_ADDR=$(otool -oV $EXECUTABLE | awk '/TrackingAuthorizationManager/{found=1} found && /getTrackingAuthorizationStatus/{f=1} f && /imp/{print $2; exit}')
printf '\x40\x00\x80\xD2\xC0\x03\x5F\xD6' | dd of=$EXECUTABLE bs=1 seek=$(($FUNC_ADDR)) conv=notrunc
codesign -fs- $EXECUTABLE
2. 自动登录闪退 ISSUE-005
通过终端指令修复:
EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.wemadeconnect.ios.lostdgl.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
实况足球(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
天涯明月刀手游
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. CPU占用异常偏高 ISSUE-004
使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。
CrossOver
目前无法运行,启动后黑屏卡住,不支持VP9视频编码。
相关帖子:CrossOver Mac forum
Wine(国际服)
使用 Wine Staging 11.0 + DXMT 0.71 可正常运行。
1. 安装Homebrew
如果网络连接不上,请自行查找“Homebrew国内镜像”。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
2. 安装Wine Staging
brew install --cask --no-quarantine wine@staging
3. 安装DXMT
下载 dxmt-v0.71-builtin.tar.gz 并解压,此为第一个目录。
打开访达,在应用程序中找到Wine Staging,右键显示包内容,进入Contents/Resources/wine/lib/wine,此为第二个目录。
将第一个目录的x86_64-unix中所有文件拷贝到第二个目录的x86_64-unix。
将第一个目录的x86_64-windows中所有文件拷贝到第二个目录的x86_64-windows,选择全部替换。
4. 安装Steam
brew install winetricks
winetricks fakechinese
winetricks steam
5. 运行Steam
wine ~/.wine/drive_c/Program\ Files\ \(x86\)/Steam/Steam.exe
卸载步骤
rm -rf ~/.wine
brew uninstall winetricks
brew uninstall --cask wine@staging
Wine(日服)
使用 Wine Staging 11.0 + DXMT 0.71 可正常运行。
1. 安装Homebrew
如果网络连接不上,请自行查找“Homebrew国内镜像”。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
2. 安装Wine Staging
brew install --cask --no-quarantine wine@staging
3. 安装DXMT
下载 dxmt-v0.71-builtin.tar.gz 并解压,此为第一个目录。
打开访达,在应用程序中找到Wine Staging,右键显示包内容,进入Contents/Resources/wine/lib/wine,此为第二个目录。
将第一个目录的x86_64-unix中所有文件拷贝到第二个目录的x86_64-unix。
将第一个目录的x86_64-windows中所有文件拷贝到第二个目录的x86_64-windows,选择全部替换。
4. 安装游戏启动器
wine ~/Downloads/BlueArchive_JP_Gamelauncher-1.7.2-setup.exe
5. 运行游戏启动器
第一次启动游戏会黑屏几分钟,请耐心等待。
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. 使用同样的命令运行启动器
卸载步骤
rm -rf ~/.wine
brew uninstall --cask 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
仅国区商店有上架iOS版,外区未上架。
商店页面显示“未针对macOS验证”,即开发者并未对Mac进行适配。
-
存在默认键位卡手问题,且部分技能没有绑定按键,手柄则一切正常。
-
存在CPU占用异常偏高的问题。
PlayCover
1. 短暂运行后闪退 ISSUE-012
使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“blockSleepSpamming”选项。
2. 默认键位卡手问题 ISSUE-008
通过按键映射去覆盖默认键位即可。
3. 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
因反作弊无法运行。
如何打开DMM Game Player:
- 添加命令行参数
--in-process-gpu - 在浏览器中登录帐号后,鼠标放在“アプリを開く”按钮上,右键拷贝链接
- 点击CrossOver界面右上角的“运行命令”
- 在命令一栏中粘贴链接,运行后完成登录
永恒之塔2
App Store
有上架iOS版,可正常游玩。
目前的问题:不支持隐藏鼠标,无法绑定技能到鼠标左右键。
Tip
访达菜单 - 前往 - 前往文件夹,输入
~/Library/Containers/AION2可打开应用数据目录。解锁60帧和减少发热的方法请看下文。
PlayCover
1. 鼠标点击异常 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平台。
棕色尘埃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\x20\x0A\x91\xE1\x04\x00\xD0\x21\x60\x22\x91' | dd of=$EXECUTABLE bs=1 seek=$((0x36A94)) conv=notrunc
printf '\xF4\x03\x17\xAA\xAA\x00\x00\x14' | dd of=$EXECUTABLE bs=1 seek=$((0x36AE4)) conv=notrunc
codesign -fs- $EXECUTABLE
3. 使用苹果帐号登录
请严格按照以下步骤操作:
- 确认是否已执行上述第二条中的指令
- 确认是否启用了PlayChain(右键游戏图标 - 设置 - 绕过设置 - 启用PlayChain)
- 禁用SIP
- 正常载入系统,终端执行
sudo nvram boot-args="amfi_get_out_of_my_way=0x1 ipc_control_port_options=0",重启电脑 - 正常载入系统,从PlayCover界面打开游戏并登录苹果帐号,关闭游戏后等待10秒
- 启用SIP
- 正常载入系统,测试苹果帐号登录状态
Warning
受限于PlayCover保存PlayChain数据的实现方式。
- 关闭游戏后,距离下一次打开最好超过10秒,否则会造成PlayChain数据丢失。
- 每次都从PlayCover界面启动游戏,不要从程序坞、启动台或访达界面启动游戏。
4. 方向键映射问题 ISSUE-007
使用PlayCover Nightly版,在编辑模式中选中WASD控件,更改为自由摇杆模式。
5. CPU占用异常偏高 ISSUE-004
使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。
CrossOver
目前无法运行,logo界面会卡住。
Wine
使用 Wine Devel + DXMT 0.72 可正常运行。
最终幻想14:水晶世界
PlayCover
1. 进入登录界面时黑屏 ISSUE-001
通过终端指令修复:
rm -r /Users/$USER/Library/Containers/com.tencent.tmgp.fmgame/Data/Documents/Users/$USER/Library/Containers/com.tencent.tmgp.fmgame/Data && ln -sf /Users/$USER/Library/Containers/com.tencent.tmgp.fmgame/Data /Users/$USER/Library/Containers/com.tencent.tmgp.fmgame/Data/Documents/Users/$USER/Library/Containers/com.tencent.tmgp.fmgame/Data
2. 摇杆映射问题 ISSUE-007
使用PlayCover Nightly版,在编辑模式中选中WASD控件,更改为自由摇杆模式。
3. 技能拖拽释放问题
方法一:点击查看教程
方法二:点击按钮的边缘也可以直接触发技能,在边缘上放置按键映射即可。
4. 打不了字
临时解决办法:右键游戏图标 - 设置 - 键盘映射设置,禁用“按键映射布局” 或 禁用“智能按键映射”。
5. 麦克风权限问题 ISSUE-016
使用PlayCover Nightly版,右键游戏图标 - 设置 - 绕过设置,启用“checkMicPermissionSync”选项。
6. 运行帧率低/发热严重
右键游戏图标,选择“显示应用数据”,进入最终幻想14:水晶世界/Data/Documents/FGame/Saved/Config/IOS,创建DeviceProfiles.ini,然后用文本编辑打开DeviceProfiles.ini:
[iPadPro5_129 DeviceProfile]
CVars=r.MobileContentScaleFactor=1.5
右键游戏图标 - 设置 - 图像设置,查看选定的iOS机型:
- 如果是M1 iPad,则保持不变
- 如果是M2 iPad,则将
iPadPro5_129改为iPadPro6_129 - 如果是M4 iPad,则将
iPadPro5_129改为iPadPro7_13
可任意修改等号后面的数值。数值越小,画面越糊,运行越流畅,发热越少。
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
codesign -fs- $EXECUTABLE
2. 画面显示不全
通过终端指令修复:
国服:
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
国际服:
EXECUTABLE=~/Library/Containers/io.playcover.PlayCover/Applications/com.proximabeta.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
3. 国服兑换码界面问题 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
4. CPU占用异常偏高 ISSUE-004
使用PlayCover Nightly版,右键游戏图标 - 设置 - 杂项设置,启用“limitMotionUpdateFrequency”选项。
CrossOver
不支持运行WeGame,因反作弊无法运行。
问题列表
- 001 虚幻引擎文件路径错误
- 002 虚幻引擎字符串解码失败导致闪退
- 003 虚幻引擎鼠标点击异常
- 004 CPU占用异常偏高
- 005 FirebaseSDK读取登录状态失败
- 006 虚幻引擎打不了字
- 007 摇杆映射问题
- 008 Unity默认键位卡手问题
- 009 虚幻引擎缺少Entitlement
- 010 Process Forked报错
- 011 查询可用运行内存的API返回错误结果
- 012 神秘闪退
- 013 Unity游戏屏幕方向错误
- 014 上层View导致按键映射失灵
- 015 Game Center登录界面不显示
- 016 腾讯游戏麦克风权限问题
- 017 WebView界面打不了字
- 018 NeoX引擎文件路径错误
- 019 UI界面屏幕方向错误
- 020 神秘闪退
- 021 QTWebEngine界面加载问题
- 022 App跟踪询问窗口不显示
- 023 CRIWARE多线程死锁问题
- 024 Unity KeyboardDelegate重复初始化
- 025 灵犀互娱SDK网页显示问题
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读取登录状态失败
常见表现
使用谷歌帐号登录的游戏,第二次打开时出现闪退,或是需要重新登录。
相关源码
- (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);
}
}
原因分析
在Unity引擎中可以通过两种方式去捕获键盘输入,一种是使用旧的API,即Input.GetKeyDown(),另一种是使用最新的Input System Package方式。如果游戏选择使用旧的API,就会出现键位卡手的问题。
iOS系统从14.0开始才有提供访问键盘设备的API,即GCKeyboard。而在此之前Unity就已经写好了UnityView+Keyboard.mm,只不过Unity是通过UIKeyCommand取巧的方式来实现的。
UIKeyCommand只支持监听按键按下事件,并不支持按键抬起事件。Unity则通过“0.5秒后自动松开”来模拟按键抬起,也就造成了游戏过程中按键卡手的情况。
解决方法
玩家方面:通过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返回错误结果
常见表现
游戏提示“设备性能不达标”。
游戏采用最保守的内存管理策略,导致渲染距离极低、材质质量极低。
原因分析
PlayCover中的应用都是以Mac Catalyst模式运行的。
iOS上有一个用于查询可用运行内存的函数os_proc_available_memory,此函数在Mac Catalyst环境下总是返回 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游戏)。
- 使用UABEA打开resources.assets。
- Filter只保留MonoBehaviour,找到CriWareIntializer。
- 选择Export Raw。
- 打开UABEA导出的文件,修改iosEnableSonicSync为false,即\x01\x00\x00\x00修改为\x00\x00\x00\x00。但是对于不同版本的CriWare插件,数据位置可能不一样。以圆哆啦为例,数据位置在0xDC,所以可以在0xDC往前往后4个字节查找\x01\x00\x00\x00,逐一尝试替换。
- 选择Import Raw。
- 保存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,触发断言失败。
解决方法
这个断言失败并不影响游戏运行,直接屏蔽+[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这个条件判断。
教程
PlayCover映射技能轮盘
-
在映射编辑模式中,点击轮盘按钮所在位置。
-
选择左下角鼠标图案的按钮,创建一个Mouse映射。
-
按下键盘上的任意键,以Tab键为例。
-
退出映射编辑模式,按住Tab键触发轮盘,此时挪动鼠标可以调整选中项。
Note
手柄方面暂不支持映射技能轮盘。
PlayCover映射方案切换
映射方案切换是PlayCover Nightly版新增的功能,PlayCover稳定版不支持。
-
右键游戏图标,选择
playapp.keymap。
-
点击
playapp.emptyKm,新建一个映射方案。
-
输入映射方案的名字。
-
右键菜单支持更多操作。
-
运行游戏后,通过快捷键 command + [ 或 command + ] 切换映射方案。
-
启动游戏后会先使用默认方案:
按下 command + ] 切换方案,屏幕中央提示“Switched to next keymap”。
为新方案设置映射:

PlayCover Nightly版翻译补全
PlayCover Nightly版作为早期测试版本,很多文本都还未完成翻译,但我们可以自己翻译并替换文件。
-
打开访达,在应用程序中找到PlayCover,右键显示包内容
-
进入
Contents/Resources/zh-Hans.lproj -
下载Localizable.strings进行替换
-
进入
Contents/Frameworks/PlayTools.framework/Resources/zh-Hans.lproj -
下载Playtools.strings进行替换
Tip
strings文件可以用文本编辑工具打开进行编辑。
虚幻引擎ini配置修改
如何找到ini配置目录
右键游戏图标 - 设置 - 详细信息,其中的“可执行文件名称”通常是项目名ProjectName。
右键游戏图标,显示应用数据,ini配置会在以下两个目录之中:
Data/Documents/{ProjectName}/Saved/Config/IOSData/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游戏有效)
解锁30帧限制
Important
此方法主要用于应对锁死30帧的游戏,不适用于想要突破60帧限制的情况。
虚幻引擎在iOS上的帧率限制由三个地方控制:
Engine.ini中的FrameRateLockGameUserSettings.ini中的FrameRateLimit- 游戏代码中动态设置
t.maxfps
其中FrameRateLock的优先级最高。
例如FrameRateLock=30, FrameRateLimit=60, t.maxfps=60,这种情况最终会是锁30帧。
只要一个游戏没有用t.maxfps来限制帧率,我们就可以通过修改ini来解锁帧率。
如果游戏设置界面中没有帧率调节选项,那这个游戏大概率也是没有用到t.maxfps的。
如何修改FrameRateLock?
打开Engine.ini,添加以下内容:
[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
FrameRateLock=PUFRL_60
如果需要更高的帧率,可改成:
[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
FrameRateLock=PUFRL_None
decrypt.day如何申请砸壳
登录网站
点击网站右上角的Login按钮进入登录页面。
如果手上没有这两种帐号,可以尝试用谷歌邮箱或Outlook邮箱去注册一个Discord帐号。注册Discord帐号时可能会遇到封号的情况,请自行解决。
获取App Store链接
申请砸壳需要提供应用的App Store链接。
1. 如果站内已经存在这个应用
-
在STORE Link的位置上右键选择“拷贝链接”即可。
2. 如果站内还没有这个应用
-
在浏览器中复制打开 https://apps.apple.com
-
在页面底部点击 United States

-
选择对应的地区

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

-
拷贝地址栏中的链接

Tip
除此之外,还可以通过以下方法获取:
- 在搜索引擎中搜索“游戏名 地区名 appstore”,例如“金铲铲之战 cn appstore”。
- 直接向 AI 询问。
申请砸壳
在decrypt.day网站中点击Request Decrypt:
填入应用的App Store链接:











