一次简单的PC游戏汉化

作者:leexuany(小宝)

前言:同样的问题,一千个程序员有一千零一种解决办法。这直接导致了在游戏本地化的过程中,不会存在一个通用的方法。没有不能汉化的游戏,但你得自己想办法。

正文:
此次汉化的对象是《剑芒罗曼史2》PC日文版。

一、修改图片

首先是分析文件。浏览游戏安装目录,不难发现大量的mcg文件,这是游戏自己的一个256色压缩图片,因为已经有人做出了解图程序,那我就可以省点事了。解图程序代码你在baidu一搜就能看到。

用解图程序解出所有mcg文件后,我们就得到了对应的bmp文件,用系统带的画图程序就可以编辑。

这里提示大家一点,这款游戏可以识别mcg和bmp图片,所以如果不是特别在意硬盘空间的话,就不需要将bmp压回mcg格式的,只需把后缀名.bmp改成.mcg即可。

游戏中大部分界面是图片控制的,这里只要修改对应的图片即可,以开始菜单(openmenu)为例,修改"openB01_A.mcg"、"openB01_D.mcg"、"openB01_N.mcg"的图像之后,游戏截图。

唉,又是修改图片,是不是有点失落?
在汉化中,修改图片是比较简单的一个环节,适合初学者。如果你确定自己有一点点汇编的知识,并且对学习汉化充满信心,那么就继续吧。

二、修改文本

这个环节,说简单也简单,说麻烦也麻烦,一切皆要看你的造化了。寻找文本,一是要看你是否有足够的耐心,二是要看你是否有足够的技巧。一般的方法是先确定文本所在的文件,然后再确定文件中文本所在的位置。如果游戏的制作者是国际顶级水准,在开发之处就考虑到了将来要全球发行,那么他可能将文本放在简单的易于处理的文本文件中,并预留多种文字编码的接口。但不幸的,很多游戏并非如此。为了速度,脚本是经过编译的字节码,或者是像《剑2》这样,事件、对白都是硬编码到dll文件中(小宝认为硬编码到dll中应该说是一个极其偷懒的做法,开发者连脚本解释器都省了)。

好了,抱怨之后,开动你的聪明智慧,找出文本吧。这里我推荐FileMon这款软件,它可以帮你监视那些文件被读取了。

这里我以战斗胜利后的文本为例,我在resident.dll中找到了它。其实,你找什么文本都无所谓,只要你能在任何想看到它的时候让它显示就可以了。主要目的是测试文字编码用。

一次简单的PC游戏汉化_第1张图片

首先,我们用WinHex把相关文字改成“战斗胜利”,进入游戏,打一架看看,哈哈变了,不过是乱码了,而不是我们想要的简体中文。

一次简单的PC游戏汉化_第2张图片

看来还要改些什么。

大家玩了这么多年的游戏,一定记得有好多台湾过来的RPG对白都是Big5码的,玩的时候还要用个内码转换,否则全是乱码,不知所云。这就奇怪了,一个JIS码的日文游戏,在我简体中文XPHome上竟然能正常显示!

用WDasm加载,看看到底用了什么函数。TextOutA、CreateFontIndirectA。。。(后来确定这款游戏没有用DirectX,难怪比ED5调试起来舒服多了。难道是GDI作图,汗)

与文字相关的函数,数CreateFontIndirectA最可疑,上MSDN查查看。果然。。。

HFONT CreateFontIndirect(
  CONST LOGFONT* lplf   // characteristics
);

参数是一个LOGFONT结构。

typedef struct tagLOGFONT {
  LONG lfHeight;
  LONG lfWidth;
  LONG lfEscapement;
  LONG lfOrientation;
  LONG lfWeight;
  BYTE lfItalic;
  BYTE lfUnderline;
  BYTE lfStrikeOut;
  BYTE lfCharSet;
  BYTE lfOutPrecision;
  BYTE lfClipPrecision;
  BYTE lfQuality;
  BYTE lfPitchAndFamily;
  TCHAR lfFaceName[LF_FACESIZE];
} LOGFONT, *PLOGFONT;

其中lfCharSet用来指定要使用的字符集,可以是SHIFTJIS_CHARSET、GB2312_CHARSET、CHINESEBIG5_CHARSET等等。

用bpx CreateFontIndirectA看看,运行,断下了,那个参数是多少,80H,就是那个SHIFTJIS_CHARSET

把它改成GB2312_CHARSET试试,一连改了n多个86H,终于改的差不多了,运行。再打一架看看。改成简体中的“战斗胜利”正常显示了,别的还是JIS码的原文,这里自然是乱码了。

一次简单的PC游戏汉化_第3张图片

哈哈,测试成功,快点把dll中所有调用CreateFontIndirectA函数的80参数都改成86。(200多个啊,我只改了60个重要的,累死了)

最后,就要确定所有的文本了。但是硬编码的dll真的很变态。请看

1000103E   | .   68  14600D10   push    100D6014        ;  / Arg2  =  100D6014
10001043    | .   68   00010000    push     100                     ;  | Arg1  =   00000100
10001048    | .  8BCF          mov     ecx, edi                   ;  |
1000104A  
| .  E8 615F0C00   call    100C6FB0           ; Act01.00976FB0

 push 100D6014 这指的就是第一句话文本的开始地址

这个既然是硬编码到dll中的,也就没有什么写程序提取脚本的必要了,
除非精通PE格式,我是不行了。

如果想做的精确点,那就只能在OD中查看所有调用的参数了。我这里
记录了几个,修改测试通过。

当然,为了完美的汉化,我们可能还会遇到修改文本指针等问题,
还是因为dll硬编码的缘故,先得过且过吧。
 

你可能感兴趣的:(游戏,struct,脚本,测试,dll,byte)