爱相随 iM/iR/iN 追加服装解锁

追加服装
爱相随 iM/iR/iN 的 1.7.5 版本更新了外出模式(おでかけモード),在新模式中和女友一起出行,在抵达设定的目标点后,会结算出行的里程并获得外出点数(おでかけポイント)。3000 外出点数可以兑换一套服装,可供解锁的追加服装共有 15 套。在打开应用服装(コスチュームの適用)开关之后,就会在满足条件时随机更换已解锁的服装。
由于外出模式中的地图数据无法加载,即便用虚拟定位抵达了目标点,外出模式也不会进入结算,因此已经无法获得外出点数,也就无法解锁服装。
参考资料
解决方法
这里以爱相随 iR 为例,使用数据线把 iPhone 连接到 PC,使用爱思助手进行文件编辑操作。
如果 iPhone 上安装有 Filza 或类似的文件管理器的话,也可以直接在手机上进行文件编辑操作。
首次运行应用程序并设置生日后,会在应用程序目录的 /Library/Preferences/ 里生成 jp.konami.loveplus.ar.rinko.plist 文件。

在爱思助手中直接打开该文件,它的内容如下。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>setting_vol_sound_effect</key>
<integer>64</integer>
<key>birthsetting_day</key>
<integer>28</integer>
<key>birthsetting_year</key>
<integer>2004</integer>
<key>birthsetting_month</key>
<integer>5</integer>
<key>setting_from_ver01</key>
<true/>
</dict>
</plist>可以发现里面只保存了生日和一些设置信息。如果我们调整了应用程序设置里的选项,这里也会保存更多设置信息。
然后添加以下的内容进去。
<key>setting_rdp</key>
<integer>99999999</integer>这样会把外出点数修改为 99999999,当然也可以换成其他任意数字,购买全部 15 套服装只需要 15 × 3000 = 45000 外出点数就足够了。
如果不想手动购买服装,也可以添加以下的内容进去。
<key>setting_costume</key>
<array>
<integer>32767</integer>
</array>这样会直接解锁全部 15 套服装。
为什么是 32767?
这个值是位掩码(BitMask),为了让 15 套服装全部解锁,需要让 15 位 Bit 的值全部为 1(111111111111111),然后再把二进制值转换为十进制值,也就是 2^15 - 1 = 32767。同理,如果希望只解锁前 8 套服装(11111111),需要把值改为 2^8 - 1 = 255。

完成修改后,不要忘记点击保存。

过程记录
虽然推断出外出点数数量和服装解锁信息应该和其他设置信息一样,都会被存在 plist 里,但在外出点数为 0 和没有解锁任何服装的情况下,应用程序不会往 plist 里写相关的信息,不知道键的名字和数据类型,还是没法修改。
在 PC 上用 SSH 连接安装了 OpenSSH 的 iPhone,使用终端操作 Cycript,附加到爱相随 iR 的应用程序进程上进行调试。
首先使用 strings 提取应用程序的可执行文件中的所有字符串,从中查找包含 Costume 的字段。
+[SettingsCtrl LoadCostumeFlag]
+[SettingsCtrl SaveCostumeFlag:]找到了这样看起来像是对象和函数的组合,负责加载和保存服装 Flag,字面意思就是解锁标志。
操作应用程序进入服装购买界面,用 Cycript 调用 LoadCostumeFlag,返回了一个空的数组,毕竟我们一套衣服都没有。
cy# [SettingsCtrl LoadCostumeFlag]
@[]创建一个只有一个 1 的数组,调用 SaveCostumeFlag 把它存进去。
cy# var flag = [@[] mutableCopy]
cy# [flag addObject:@1]
cy# [SettingsCtrl SaveCostumeFlag:flag]这时候 plist 文件里就出现了服装解锁的信息,第一件服装也被解锁了。
<key>setting_costume</key>
<array>
<real>1</real>
</array>只解锁了第 1 套服装,下面做一些修改实验。
<key>setting_costume</key>
<array>
<real>1</real>
<real>1</real>
...
<real>1</real>
<real>1</real>
</array>还是只解锁了第 1 套服装。
<key>setting_costume</key>
<array>
<real>1</real>
<real>2</real>
</array>
还是只解锁了第 1 套服装。
<key>setting_costume</key>
<array>
<real>2</real>
<real>1</real>
</array>只解锁了第 2 套服装。
通过以上的解锁情况,已经可以推断出来,应用程序只读数组的第一个值,而且这个值应该是个位掩码,用二进制值来控制每套服装的解锁情况。
<key>setting_costume</key>
<array>
<real>255</real>
</array>解锁了前 8 套服装,思路正确了。
最后还是把 Real 换成 Integer 了,虽然用起来没差别,但是原本 plist 里都是 Integer,统一一下~
<key>setting_costume</key>
<array>
<integer>32767</integer>
</array>再次翻了翻保存所有字符串的文档,发现外出模式相关的函数都叫 RealDate,于是从中查找包含 RealDate 的字段。
+[SettingsCtrl SaveRealDatePoint:]
+[SettingsCtrl LoadRealDatePoint]这应该就是服装购买界面里负责加载和保存外出点数的函数了。
操作应用程序进入服装购买界面,在 Cycript 里调用 SaveRealDatePoint,直接存个 999999,然后再调用 LoadRealDatePoint 检查一下结果。

果不其然,猜对了。
这时候 plist 里也终于出现负责存储外出点数的键,以后就可以直接改 plist 来修改了。
<key>setting_rdp</key>
<integer>999999</integer>完成 🎉