(PS)かまいたちの夜•特別篇 汉化笔记 八

8.           脚本文件分析 II

各个指令的参数可分成5种:

1、文本,以0结尾,只出现在指令00中;

2、段号,2byte,出现在段跳转指令中;说明见上

3、地址,2byte,指向某条指令的地址,出现在段内跳转指令中。

4、文件号,2byte,相应pac的子文件号,出现在显示声音、背景、阴影的指令中。

5、其他。

 

同时也有部分指令没有参数。

之后为了更好地分析脚本,将脚本文件导出成html格式,对各个段加上锚点,段跳转指令中加上超链接。

然后就可以一边游戏一边分析各个指令的大致含义。

 

这里面还有一个问题,就是脚本结束在什么地方?初次导出的时候出现很多00指令,后面又没有文本,其实脚本已经结束,后面填充了大量的00而已。

原始脚本在这之前跳转走了,但是跳转指令又很普遍,我怎么知道何时是脚本结束呢。

 

第一个特征就是00指令的参数也是00,基本能适用于大多数脚本。但我还发现有些脚本尾部有一些不明数据,这些数据并不是指令+参数的组合,它们也紧贴着脚本,让我不能用00来区分,如果按照指令去分析也会出错。

这时候可以用01跳转指令+段号来区分,如果是最后一段而且又是01指令,那么标志脚本结束。

这时我想到应该有指令使用了脚本后面的这些数据,观察下来是指令39。不过这是文本导入,重建脚本时候的事情了。

 

具体代码参考FuckSce

 

注:其实一开始也只知道段号类型和文本类型,文件号是之后分析出来的,不断地深入,慢慢地覆盖更多的指令。

而地址类型是最后知道的,因为中文文本导入之后地址出现了变化,最后在某些地方报错。

只是段内跳转很少看到,所以这个类型最后才被发现。

 

这个问题我详细说一下吧。初始测试的时候,在输入犯人名字的地方,写好犯人名字,然后程序就崩溃,开始显示大量的文本,从头至尾不停地刷屏。

脚本在0D:2C,如下:

1dd0 - 09: 28 00 01    // 首先我觉得问题出在输入部分,于是检查这部分的函数
                       // 这里进入输入犯人名字的界面,输入结果放入n0
1dd4 - 09: 28 00 05    // 这里根据n0,到表中查找,然后选择一个统一的名字放入n5
                       // 比如美树本洋介,可以输入美树本,也可以输入洋介,也可以输入全名,但最后放入n5的是美树本先生
                       // 并且根据选中的名字返回0-5 6个值,应该对应下面的六个分支。
                       // 载入原始光盘执行,输出都是一致的。一直到这里应该都没有问题。
1dd8 - 0B: 01
1dda - 4D: 01
1ddc - 3E:
1ddd - 57: 选择肢: 05 71  | 跳转到: 0D:2D 节点: B8 01 | 跳转到: 0D:2E 节点: B9 01 | 跳转到: 0D:2F 节点: BA 01 | 跳转到: 0D:30 节点: BB 01 | 跳转到: 0D:32 节点: BD 01 | 跳转到: 0D:33 节点: BE 01
1df8 - 1E: 7E 1E       // 执行到这里,飞掉
                       // 在函数入口下断,点击asm log,然后在返回下断,取消asm log。载入原始光盘同样操作一遍,比较两个asm log完全一致
                       // 感觉没有问题。(之后发现其实问题就是这个完全一致)
1dfb - 14: 02
1dfd - 00: v0c1
1e05 - 14: 10
1e07 - 4B: F6 32
1e0a - 02: 0D:2D
1e0d - 14: 02
1e0f - 4C:
1e10 - 0C: 延迟 32 00
1e13 - 00: v1c2
1e1b - 14: 10
1e1d - 4B: F7 32
1e20 - 02: 0D:2E
1e23 - 14: 02
1e25 - 4C:
1e26 - 0C: 延迟 32 00
1e29 - 00: v2c3
1e31 - 14: 10
1e33 - 4B: F8 32
1e36 - 02: 0D:2F
1e39 - 14: 02
1e3b - 4C:
1e3c - 0C: 延迟 32 00
1e3f - 00: v3c4
1e47 - 14: 10
1e49 - 4B: FA 32
1e4c - 02: 0D:30
1e4f - 14: 02
1e51 - 4C:
1e52 - 0C: 延迟 32 00
1e55 - 00: v4c5
1e5d - 14: 10
1e5f - 4B: FB 32
1e62 - 02: 0D:32
1e65 - 14: 02
1e67 - 4C:
1e68 - 0C: 延迟 32 00
1e6b - 00: v5c6
1e73 - 14: 10
1e75 - 02: 0D:33
1e78 - 14: 02
1e7a - 00: c0
1e7e - 16:
 

    之后就陷入了痛苦的调试了,此时下的断点还是内存访问断点,根据对脚本的读取来判断情况。

    现象是进入1E指令后,突然读取了前面的位置。

 

我感觉问题出在复杂的57指令中,这个指令应该是最复杂的指令了,它指明选择的跳转和节点,然后还和下面的许多指令配合用来显示选择画面。

执行这条指令的时候,不但会读取下面的指令,还会载入其他脚本,读取指定的段落。

    我以为是57指令中,或者下面的某个向前跳转的指令参数出现问题,但是不知道是哪个参数。在两次断点间进行asm log,代码也过多,分析不出什么。

 

我感觉下的断点不对,于是换成了pc断点,下断的位置就是第二套函数的跳转处,这样就能知道飞掉前执行了什么函数。

但最后还是看到执行到1E就飞掉,这是做了asm log的比较,发现完全一致,问题似乎不在这个指令。(这里如果不做比较,而是配合IDA走一遍的话也许也能解决问题)

 

这时我突然觉得应该换个断点,对全局变量script_cur_pos下写入断点,当然同时还配合pc断点。然后我发现进入1E后,script_cur_pos有了一个大的变化。

立刻在IDA中找到这行指令,发现由于某个全局变量的控制,进入了一个分支,这个分支中script_cur_pos会变成1E指令的参数1E7E

 

就这么简单的一个事情,为什么前面下内存访问断点没有发现呢?因为这个时候pos改变已经是结果了,而下写入断点,可以抓个现行,直接定位到代码,发现是指令1E的问题,那么立马就能联想到1E的参数就是跳转地址。

而内存访问断点只是告诉你现在飞掉了,到底怎么飞的一点头绪也没有,之后下pc断点算是更加地误入歧途。所以一个简单的问题,因为下断不好困扰了我一阵。

 

另外一开始我生成脚本分析html时,并没有加上地址,所以没有注意到1E参数的含义,或者说由于已经知道了段跳转,就没有考虑段内跳转,也算是一个思维误区吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值