在0xd9c5c处 这里发现r5是从[r4+48]得到的,r4为0x1fcb40.
但是查看[1fcb40+48]处,并不能找到线索.
我们继续看上层函数0x900EC.
我们在0x900E4处下个断点,重新读取光盘生成怪物.
发现这里的指令是跳转到r2寄存器中存储的地址,会很频繁的触发断点,这里必须要对r2做限制才行.
尝试了多次还是没办法在0x900E4处下断点,因为不知道0x900E4这里要跳转到的R2是多少,无法设置条件断点.
似乎方向不对,还是回到0xd9c5c这个位置,既然找到了R5的读取来源内存[1fcb40 +48],显然这个内存地址是在读取CD后,根据CD中的数据被计算出来并被写入这个地址的,R5的数据其实就来自这个内存地址.
我们尝试直接读怪物农场2的镜像,发现[1fcb40 +48]这个位置写入的值是0x19,对应编号26(0x19+1)的怪物モッチー,也就是怪物农场2自身镜像对应的怪物的种族Id.
所以前面的推理是正确的,从CDROM中的读取数据后.会将怪物的种族id,写到[1fcb40 +48]处.
注意这里的1fcb40是存在r4中,值是动态的,每次调试可能都不同,需要从0xd9c5c下断点获得.
先存好档,重新在0xd9c5c下断点并生成怪物,发现r4是0x1ffc50.
这样的话,我们只要在[0x1ffc50+48]处下个内存断点,在读取CDROM数据的时候应该会触发该断点.
发现在换盘并按确定的那一刻,触发了断点.此时正在将r2的值0x2020写入[0x1ffc50+48],而r2的值是从r7[0x76868]读取的.
简单调试了下,发现这边似乎是从CDROM读取数据后,将数据写到了[0x1ffc50+48]开始的这一片内存中.
我们之前推测是根据怪物Id,决定最后会生成的怪物的.那是否怪物Id也是在这个时候写入的?
三色鸟的Id是0x148,但是在这块内存附近找不到0x48,0x01这样的数据.
如果我们在读取CDROM并写入[0x1ffc50+48]后,修改存储在这里的种族Id,会发生什么?
之前就很喜欢甲虫,也很难入手,甲虫的种族Id是5,在内存中就是0x04,我们直接把[0x1ffc50+48]处的两字节改成0x04,0x04,因为甲虫初期无法生成,所以也顺便把"种族允许生成"列表+4的位置写1(0x97336+5-1 = 1).
继续执行,然后换回怪物农场2的镜像,生成怪物.
果然成功了.
但是为什么这里会有两个重复的种族Id?
突然想到,合体的怪物,确实有主种族Id和副种族Id之分.
我们可以用人马+龙的合体来试试,人马的种族Id是3,龙的种族Id是2.
按刚才的修改方式,读档触发数据断点,把[0x1ffc50+48]处修改成0x02,0x01.
把"种族允许生成"列表+3,+2的位置写1(0x97336+3-1 = 1, 0x97336+2-1 = 1).
重新生成,发现真的生成了人马+龙的合体.
到这一步,理论上我们可以生成所有的怪物了,除了特殊怪物.
怪物农场2中有一些特别稀有的怪物,只能通过某些特定光盘镜像生成.
比如ps游戏寄生前夜的B盘,可以生成金属液体人,就是终结者里面那个T1000,超酷的有没有.
绝对不是巧合哦,用Terminator 2 Sound Track的光盘也能生成这个怪物.
我们用寄生前夜的B盘生成怪物试试.
读光盘的时候又触发了内存断点.
可以看到,液态金属人的主种族Id是0x1C,也就是28+1,29.副种族Id是0x26,也就是38+1.
怪物农场2一共只有38个种族,看起来似乎38以外的种族Id被专门用于特殊稀有怪物.
我们用种族Id为8的Golem来试试吧.
[0x1ffc50+48]处写入0x07,0x26.
"种族允许生成"列表+8的位置写1(0x97336+8-1 = 1).
好吧,虽然有点怪,但是确实是稀有怪物.
至此,我们已经可以生成所有游戏中的怪物了,包括不可用的野外怪物也可以生成.
最初的目标已经实现了一大半.
接下来会尝试分析从CDROM中读取的数据,如果可能的话,再做个简单的修改器或者光盘生成器,最好是我能直接在安卓手机上使用模拟器随意生成怪物.