## L20
接下来开始尝试汉化一些文本,后面的部分就是一些非常容易的固定的把式套路了(但也很重要!),没有需要分析的地方前面我们提到,由于shift-jis不支持大部分汉字的显示,所以我们使用GBK编码来编写一些汉化文本,这里修改snky01.ps3:

注意这里的汉化文本要比原文短,这一般是可以做到的,因为中文的平均信息熵高,如果长度超过的话,要修改机器码来重新校验长度,需要一点计算和操作,要尽量避免。进游戏看看:

发现文本已经改变,但是除了兼容的英文,其他的符号和汉字都是乱码。原因很简单,前面已经分析过,这是由于用jis的解码格式解GBK编码导致的。要修正很简单,再主模块cmvs搜索:createfont
(这是一个非常常用的图像渲染win api,请熟记!)并打上断点:

进入游戏后停在createfonta内部,这时候按enter回到调用fonta的地方:

看到红圈圈出的地方了吗?这是典型的CreateFontA结构,push就是传递参数,push 0x80,push 0x00...这些相当于CreateFontA(0,0,0,0,0,0,0x80,...)
这是CreateFontA完整的函数签名:
```C
HFONT CreateFontA(
int nHeight, // 字体高度
int nWidth, // 字体宽度
int nEscapement, // 文本行倾斜角度
int nOrientation, // 字符倾斜角度
int fnWeight, // 字体粗细
DWORD fdwItalic, // 是否斜体
DWORD fdwUnderline, // 是否下划线
DWORD fdwStrikeOut, // 是否删除线
DWORD fdwCharSet, // 字符集
DWORD fdwOutputPrecision, // 输出精度
DWORD fdwClipPrecision, // 裁剪精度
DWORD fdwQuality, // 渲染质量
DWORD fdwPitchAndFamily, // 字体系列
LPCSTR lpszFace // 字体名称);
```
那么我们要改的是哪部分呢?
就是push 0x80部分,0x80这个常数是硬编码在gdi32中的一个数字,这是shift-jis的编号,而我们的gbk对应的编号是0x86,我们按空格把80->86即可。
这边再看一眼蓝圈圈住的部分,这个就是就是一个栈帧,一个栈帧就代表一次函数调用,在x64dbg中会用一个一个黑色的线夹住,顶部的叫esp,底部的叫ebp,中间包裹的都是函数的参数,比如我蓝色箭头指向的就是前面传入的0x80参数。

像这样重复多改几次,因为游戏中不止一处调用CreateFontA,历史对话等等都要调用,都是一样的操作,反正记住都改80-86就好。然后改完后再进入游戏,发现还是显示不对
:

这是为什么呢?
接下来开始尝试汉化一些文本,后面的部分就是一些非常容易的固定的把式套路了(但也很重要!),没有需要分析的地方前面我们提到,由于shift-jis不支持大部分汉字的显示,所以我们使用GBK编码来编写一些汉化文本,这里修改snky01.ps3:

注意这里的汉化文本要比原文短,这一般是可以做到的,因为中文的平均信息熵高,如果长度超过的话,要修改机器码来重新校验长度,需要一点计算和操作,要尽量避免。进游戏看看:

发现文本已经改变,但是除了兼容的英文,其他的符号和汉字都是乱码。原因很简单,前面已经分析过,这是由于用jis的解码格式解GBK编码导致的。要修正很简单,再主模块cmvs搜索:createfont

进入游戏后停在createfonta内部,这时候按enter回到调用fonta的地方:

看到红圈圈出的地方了吗?这是典型的CreateFontA结构,push就是传递参数,push 0x80,push 0x00...这些相当于CreateFontA(0,0,0,0,0,0,0x80,...)
这是CreateFontA完整的函数签名:
```C
HFONT CreateFontA(
int nHeight, // 字体高度
int nWidth, // 字体宽度
int nEscapement, // 文本行倾斜角度
int nOrientation, // 字符倾斜角度
int fnWeight, // 字体粗细
DWORD fdwItalic, // 是否斜体
DWORD fdwUnderline, // 是否下划线
DWORD fdwStrikeOut, // 是否删除线
DWORD fdwCharSet, // 字符集
DWORD fdwOutputPrecision, // 输出精度
DWORD fdwClipPrecision, // 裁剪精度
DWORD fdwQuality, // 渲染质量
DWORD fdwPitchAndFamily, // 字体系列
LPCSTR lpszFace // 字体名称);
```
那么我们要改的是哪部分呢?
就是push 0x80部分,0x80这个常数是硬编码在gdi32中的一个数字,这是shift-jis的编号,而我们的gbk对应的编号是0x86,我们按空格把80->86即可。
这边再看一眼蓝圈圈住的部分,这个就是就是一个栈帧,一个栈帧就代表一次函数调用,在x64dbg中会用一个一个黑色的线夹住,顶部的叫esp,底部的叫ebp,中间包裹的都是函数的参数,比如我蓝色箭头指向的就是前面传入的0x80参数。

像这样重复多改几次,因为游戏中不止一处调用CreateFontA,历史对话等等都要调用,都是一样的操作,反正记住都改80-86就好。然后改完后再进入游戏,发现还是显示不对

这是为什么呢?























