Programming 版 (精华区)
发信人: ffzh (★铁马冰河★), 信区: Programming
标 题: 游戏汉化教程--2
发信站: 哈工大紫丁香 (2001年03月29日16:45:09 星期四), 站内信件
当你确定你必须靠跟踪修改程序,来实现汉化时,就需要求助于大名鼎鼎的
SoftICE了。由于每个程序都有自己的一套输出字符的方式,所以不存在万能公式
可以在半小时内就奠定胜局,即使像我这样做过七八个工程的人来说,能在两小时
内就找到关键的几个地址已经是谢天谢地了。尤其是现在三维游戏的出现,大量采
用billboard技术显示文字,更是让人捉摸不定,无从下手。
不过写字符毕竟是简单的工作,不会牵涉到过分复杂的算法(当然也有比较复杂的
),我们总有办法破解,做个Cracker总要有点职业精神嘛。
好吧,闲话莫提,言归正传。
先设想一下,如果我们要写字符串,会用什么样的方法?
最最一般的方法就是:
void DrawString(char *string,int x,int y)
{
int position = x;
for(i=0 to strlen)
x +=DrawChar(string[I],x,y);
}
int DrawChar(char ch,int x, int y)
{
BITMAP bmp = GetFontBitmap(ch)
BitBlt(bmp,x,y);
return GetCharWidth(ch);
}
好,仔细看看这段代码,我们如何修改才能把英文string偷梁换柱,变成汉语呢?
显然是在函数DrawString的那个for循环之前,就截获string,然后翻译成中文,再
让string指向中文就可以了。光光修改string还是不够的,那样显示出来99%的可
能是乱码,因为游戏根本就不支持双字节的内码,更没有汉字字库,所以那个
DrawChar()函数也需要改造。
现在我们先来寻找假想的DrawString函数。
首先假定你已经安装了softice, 要汉化的游戏是Diablo。
第一步:运行游戏Diablo
第二步:挑选特征字符串。之所以叫"特征",就是挑选那些简单的,而且不容易应
起重复的字符串,比如"shooting house"(SWAT3),或者"Cain the
elder"(Diablo) 就是很好的特征字符串,而像"Save, Load, Yes, No, OK,
Cancel, Diablo, Weapon, Life, Mana"之类的字符串就是彻头彻尾的失败的选择
。此外还有一点考虑,就是尽量挑选可以控制其出现与否的字符串,比如鼠标移到
某个地区后出现的帮助信息。
第三步:ctrl-D进入softice, 寻找该字符串 s 30:0 l ffffffff 'Cain the
elder', 会找到若干个地址,分别记录下来。然后选择一个(或者几个),用bpm
设置内存断点。不要理会地址大于C0000000的结果,那是你自己打字打进去的结果
。
第四步:运行游戏,把鼠标移到老头子上面,让它显示'Cain the elder',这时候
可能会诱发内存中断。多运行几次,把产生中断地址都记下来(记在脑子里或者根
本不记也可以,如果你足够熟练)。
注意:产生中断的地址会有好多个,这简直不可避免,因为程序并不是简单的显示
字符串,还要牵涉到拷贝,算长度,排版处理等等一系列复杂的运算。如果花了九
牛二虎之力读代码,最后竟然发现只不过实现了拷贝功能,那会是非常非常郁闷的
事情,所以读代码这事虽然是必须的,但是一定要慎重。
第五步:好了,我们有了这么多乱七八糟的地址,该筛选一下了。
1) 首先剔除那些判断字符串为空的地方,典型的是
test esi, esi
je xxxxxxxx
2) 然后剔除循环重复的地方。如果断点A出现了1次,断点B却出现了好几次,那
么B就是一个无用的断点(虽然以后我们还会需要他们)
3) 剔除那些混杂有movsd, movsw, movsb之类的内存拷贝指令,或者scansb之类
的指令的地方,想都不用想。(当然,对于movsd之类的指令,要尤其注意edi指向
的地址,它往往就是我们以后要注意的内存断点)
4) 剔除那些莫名其妙的地方,一会儿是字符串指针,一会儿又变成一个乱七八糟
的东西,这个地址八成是局部变量,除非万不得已,不要注意他们。
5) 现在,剩下的可疑的地方就不多了。什么?一个都没了?那就找找3中edi指向
的地址,bpm一下,然后重复前面的步骤
需要注意的是,以上剔除的东西,有可能出现冤假错案,尤其注意2,以及3的edi
。
第六步:初步确定DrawString函数的地址
虽然经过筛选,仍然可能会留下好几个地址,这时候就需要耐心一点看看代码了,
呵呵。
不过总有超一流的手段快速定位,熟练是一方面,另一方面,也可以耍一点小手腕
。很简单,只要在出现某个断点时,就往内存中写一点什么东西,做个记号。比如
在第一断点出现时,把'Cain the elder'改称'Cain the 11111',第二个断点出现
时改称'Cain the 22222',以此类推,看看屏幕上显示了什么东西?'Caint the
66666'?那么就是第六号断点了。此时再深入研究代码,十拿九稳。
--
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: vilab.hit.edu.cn]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:5.019毫秒