前几天我汉化一个了基于openGL引擎游戏游戏,过程中出现游戏不显示汉字,所以无法本地化。

首先,OD加载主程序,CTRL+N找和显示有关的函数(这个只能从字面上理解某个函数是不是和显示有关),既然这个游戏使用的是OpenGL编写的,那么我们就主要看带有gl前缀和导入函数。


游戏导入的OPENGL32库中只有这么多的函数了。
如果你看过Nehe写的OpenGl的话,你会在书里的第17章中发现有关使用OpenGL显示英文的例子,书中使用了glCallLists来贴图一个数组里的图象来达到显示目的。

那么我先在glCallLists下断,F9运行游戏。

 

可以看到栈里有字符“DELETE”字符和其长度6,我们再去看下glCallLists的定义。
void glCallLists(
  GLsizei n,
  GLenum type,
  const GLvoid *lists
);
那么显示函数就是这个glCallLists函数了,函数中第二个参数1400为GL_BYTE,意思就是让glCallLists函数按8bit读取0022EC20中存放的数据,数据范围只是0~255。对于游戏所用到的汉字来说这个范围太小了,所以我们要修改这个参数,将其设置为GL_SHORT或是GL_UNSIGNED_SHORT,让glCallLists函数按16bit读取数据,其范围为0~65535足够汉字使用了。
当第二个参数改为GL_SHORT后,我们需要修改第三个参数lists,如果不修改它,那么显示数字或是必要的英文字符的话glCallLists函数总不能正确的读取数据,因此会显示错误。我们可以简单的将原来的ASCII码转换成UNICODE编码。UNICODE编码是将一个字符存放到2个字节里的,这样的话,英文和数字就可以像原来一样正确显示了。
由于glCallLists显示的是一个数组里的贴图,lists这个参数只是一个一个的提供要显示的图像所在的位置,ASCII编码中从空格(0x20)开始以及后边的字符都可以显示,所以,在NeHe和教程中,使用ASCII编码字符的数值减去0x20来对应所要显示的贴图。那么我们转换为UNICODE码后,我们需要制作自己的字符数组来将字符排序再通过glCallLists显示出来。
接下来我们把游戏中要用到的汉字全都找出来,把这些汉字组成一个不重复的表(使用UNICODE来编这个表),我们通过字符对比来重新组建一个数据串提供给glCallLists让其在游戏内部查找,编码:

WORD GetMyChar(WORD wChar)
{
CString str=L”字库字符”;
For (int i=0; i<str.GetLength(); i++)
{
                If (wChar == str.GetAt(i)
                {
                        Return (I + 128 + 32);
}
}
Return 0;
}

//修改glCallLists
WORD wNewChar[1024];
For (int i=0; i<wcslen(lists); i++)
{
        If (0 != GetMyChar(lists[i*2]))
{
        wNewChar = GetMyChar(*(PWORD)(lists+i*2));
}
Else
{
wNewChar = lists[i*2];
}
}
这样我们得到新的经过编码的字符串了!

经测试,中文可以正常显示,到此调试完毕。

PS:欢迎对游戏汉化有兴趣的朋友加我QQ:109990997,一起交流游戏汉化技巧。