怪物农场2修改日志5 - 极乐净土

接上篇,怪物农场2修改日志4 - 决战前夜

bgm,最近血洗B站的极乐净土

上篇中,我们成功的找到了从光盘中读取的数据得到的怪物种族Id和副种族Id在内存中存储的位置.

通过修改该内存位置,可以直接决定最后生成的怪物,包括特殊怪物都能直接生成.

接下来我们会看下这些数据是如何通过CDROM中读取的数据计算得到的,顺便会挖掘下其他受CDROM影响的初始怪物数据.

通过查询外文攻略站得到如下信息.

  • CD中最后一条音轨的分钟数决定了怪物的主种族Id.
  • CD中除去最后一条音轨,剩余的总时间的秒数部分,决定了怪物的副种族Id.
  • 根据CD中第一条音轨的秒数部分对怪物属性进行修正.
  • 根据CD中全部音轨的秒数部分对怪物属性进行再次修正.
  • 特殊怪物的主种族Id和副种族Id似乎是根据数据硬编码得到的,不使用通用的规则.

可以推测出,从CD中读取的信息应该是这些.

我们仍然先使用寄生前夜2的B盘来做测试,外站上看到这个盘的音轨数据如下,

0+3667秒(全部音轨长度61:07、最后一条音轨长度61:07)

继续调试看看,仍然在0x001ffc98处下个数据写入断点,看看数据是如何从CD到这个内存位置的.发现断在了如下位置,

从调用栈可以看到上层函数是0xd9a04,我们执行到返回看看.

可以看到这里会一直拷数据,将0x76868(r6)到0x76888(r9)拷贝到0x1ffc98开始的内存.

之后函数就返回到了上层.

可以看到上面有句jal 0xda0a4,因此返回前的那个函数的入口地址是0xda0a4.

我们在0xda0a4下个断点,重新调试看看具体做了哪些事情.

可以看到我们成功来到了这个函数的入口处.

首先addiu r29,r29,0xffb0,这里把r29的值减少了0x50,查了下资料发现r29是stack pointer,这里开辟了0x50的栈空间,从0x76858到0x768a8.

sw r17,0x44(r29) 这里把0x1ffe70存到了r29+0x44处.

sw r31,0x48(r29) 这里把返回地址保存到了r29+0x48处.

sw r16,0x40(r29) 这里把0x1ffd30保存到了r29+0x40处.

lbu r2,0x48(r17) 这里读取0x1ffe70+0x48=0x1ffeb8

beq r2,r0,0xda120 这里r2为0,跳转到0xda120.之后发现,如果生成时直接使用怪物农场2的盘,则这里r2为1,不会跳转

0xda120处直接跳到了0x34228

0x34228入口处,这里分配了0x20的栈空间.

sw r17,0x0014(r29) 将0x1ffe70存到栈上+0x14的地址.

r4 = 64

r5 = 4

之后将r31存到r29+14处,跳到0x3cf08

0x3cf08中暂时不容易看出太多信息,我们回到上一层继续执行.

从0x34264开始似乎在把0x1fcdd0处的数据搬到0x76890,继续执行看看.

这个时间点,从0x34228返回,由于r2为0,将跳转到0xda188.可以看到0x76890处的内存此时为0x61,0x09.

来到0xda188处.

r2 = r5 = r7 = 0x800c0000  r6 = 0x800c646c r16 = 0

接下来又做了一些意义不明的赋值.

r10 = 2  r9 = 0x76888  r4 = 0x800c6472  r2 = [0x800c6468] = 0x100

如果r16大于等于r2,则跳转到0xda2b8.否则继续执行,r3为之前保存的0x61,这个0x61看起来很像前面提到的61分钟.

直接改r3的值试了下,确实能改变怪物的种族,数值也会和外网攻略站上的一样,只是这边不知道为什么把61分钟存成了0x61.

r2,r3不相等,则会跳转到0xda2a8

这里将r4和r6增加8,又跳回0xda1a8处.此外跳转下面一条语句也会执行,所以r16每次会自增1.

再调试下,发现这里这个循环,是从1到100,根据从CD中读取的那些数据查找匹配的项.然后根据项中记录的某个整数作为偏移查找到指定的数据.

通过调试发现最终是从0xc80fc拷的数据到0x76868附近的内存,0xc80fc这里的数据是静态的,似乎记录了所有可能生成的怪物的数据,每段数据的长度是0x28,怪物属性也可以在这段数据中找到.

我们用怪物农场2的盘做实验看看现象,

使用怪物农场2的盘后发现,这里r2为1,不会跳转,所以这时的流程和读CD中的数据来生成怪物是完全不一样的.

调试发现这里检测到是怪物农场2的盘,就直接硬编码生成了种族Id为19的モッチー.

这边在0xda0ec处,我们patch这里的代码,直接改成addiu r2,r0,0x261C,就能生成前面的那只特殊的液体终结者了,其中0x26和0x1C对应了液体终结者的副种族Id和主种族Id.

简单做了个金手指用于测试,只要修改#Summon Specified Monster的前两行,不用换盘就能任意生成所有的怪物,包括野外训练中遇到的怪物.(大成功?)

#Summon Specified Monster
300DA0EC 0011
300DA0ED 0027
300DA0EE 0002
300DA0EF 0024
#Undo Summon Specified Monster
300DA0EC 0000
300DA0ED 0000
300DA0EE 00E2
300DA0EF 008C

但是这个方式并不能保证生成的怪物的数据正确,而且是直接patch代码,首先不确定这个地址是不是每次都一样,也很难保证不会有其他问题.

接下来,准备仔细的再分析下这边的几个函数,尝试找到更好的修改点,或者制作修改器.

To be continued...

时间: 2024-10-13 11:45:49

怪物农场2修改日志5 - 极乐净土的相关文章

怪物农场2修改日志3 - 年轮

接上篇,怪物农场2修改日志2 - 奇妙能力歌 bgm是神秘妹纸唱的超好听的年轮 上篇中,我们顺利找到了"已收集怪物Id"这个列表. 接下来该做什么呢? 根据上篇的推理,当玩家生成新的怪物时,游戏程序会更新这个列表,加上新的怪物的id. 我们可以设置内存断点,在生成新怪物的时机中断,然后反推出生成怪物的数据(主要是id)来自何处. 我们读取没有生成169号クリック小朋友时的游戏记录,查看9703C,也就是"已收集怪物Id"列表. 可以看到,0x97151(278号的モ

怪物农场2修改日志1 - FirstBlood

最近有朋友分享了安卓上的playstation模拟器,我又开始玩ps上的怪物农场2.这是一个怪物养成类游戏,玩家要养育,训练怪物,并参加比赛. 游戏制作公司是Tecmo,游戏中怪物的模型贴图等非常优秀,合体系统也是我见过最好的(从某种角度上看,完爆真女神转生). 该游戏有个特色系统是,可以通过ps的换盘机制,从光盘生成不同的怪物,甚至生成稀有的怪物.因此玩家需要收集各种各样的光盘(模拟器可以使用光盘镜像)来生成怪物. 虽然我10年前就开始玩这个游戏,断断续续玩了很久,还是有很多稀有的怪物收集不到

SpringBoot系列十一:SpringBoot整合Restful架构(使用 RestTemplate 模版实现 Rest 服务调用、Swagger 集成、动态修改日志级别)

1.概念:SpringBoot整合Restful架构 2.背景 Spring 与 Restful 整合才是微架构的核心,虽然在整个 SpringBoot(SpringCloud)之中提供有大量的服务方便整合,但是这些 整合都不如 Rest 重要,因为 Rest 是整个在微架构之中进行通讯的基础模式.那么对于 Rest 首先必须对其有一个最为核心的解释: 利用 JSON 实现数据的交互处理.而且 Spring 里面提供有一个非常强大的 RestTemplate 操作模版,利用此模版可以非常轻松的实

C#实体类对象修改日志记录

C#实体类对象修改日志记录 类型验证帮助类 public static class TypeExtensions { public static bool InheritsFrom(this Type source, Type target) { if (null == source || null == target) { return false; } if (source == target) { return true; } if (source.GetTypeInfo().IsGene

springboot动态修改日志级别+权限认证

1. springboot动态修改日志级别+权限认证 1.1. 需求 网上找到的动态修改日志级别的方式,基本都是没有权限验证的,或者特地关闭权限验证,但也没给出加上验证的解决方式 修改日志等级也是一个敏感操作,最好不能暴露地址直接修改,所以我研究了下,把权限验证加上了 1.2. 解决 1.2.1. pom 首先加上pom <dependency> <groupId>org.springframework.boot</groupId> <artifactId>

一个通用的通过触发器实现的,可配置的表修改日志解决方案

在MIS系统中,系统审计功能是很重要的一部分,审计的一部分就是记录数据修改日志.记录数据修改日志有很多种实现方案,有通过后台程序实现的,在修改程序中增加日志代码,也有通过数据库实现的,使用触发器来记录修改日志.本方案采用第二种方案.这种方案的优点是无论你通过什么方式修改数据,都会记录下来,极少需要修改代码:缺点是需要应用程序配合,以便能知道是哪个应用系统的账号做的修改. 本方案的核心是,通过一个配置表,配置哪些表需要记录日志.修改哪些列的时候记录日志.然后根据配置信息,为每个表生成用于记录日志的

log4j2和logback动态修改日志级别工具类

工作中,有些场景需要动态修改线上日志记录器的打印日志级别, 本文的两个工具类使用的版本如下: ----------------logback--------------------- <dependency>   <groupId>ch.qos.logback</groupId>   <artifactId>logback-core</artifactId>   <version>1.1.8</version></d

Centos7 keepalived 修改日志路径

Keepalived默认所有的日志都是写入到/var/log/message下的,由于message的日志太多了,而Keepalived的日志又很难分离出来,所以本文提供了一个调整Keepalived日志输出路径的方法.具体操作步骤如下:1. 修改 /etc/sysconfig/keepalived 把KEEPALIVED_OPTIONS="-D" 修改为KEEPALIVED_OPTIONS="-D -d -S 0" #其中-S指定syslog的facility 2

maillog修改日志保留时间

maillog默认是保留一个月,(一周1清理一次.保留4个副本) 1.修改 /etc/logrotate.conf 文件. 如果只需要保留一周,把副本改成1份.  或者把清理改成每日,然后设置不同的份 2.设置好之后,重启. /etc/init.d/rsyslog restart  服务重启一下 备注: 若删除了 /var/log/下的日志, 比如 maillog 他不会自动生成,也需要重启 rsyslog服务. 原文地址:http://blog.51cto.com/net881004/2072