冒险解谜游戏中文网 ChinaAVG

标题: [转贴] GF汉化详细教程[内核修改篇] [打印本页]

作者: shane007    时间: 2008-10-6 10:42
标题: [转贴] GF汉化详细教程[内核修改篇]
  
' {' d( ]1 m6 r经过前边的字库改造,已经完成了一半的工作,剩下最关键的显示汉字部分了。字库已经是中文的了,但是能让中文显示出来却不是件容易的事。不信现在进游戏试试,看到的中文全是乱码。为何?因为中文是双字节,两个字节才代表一个汉字。游戏显示英文字体的函数是为显示单字节的英文设计的,是不适合显示中文的,必须要修改。因为不可能得到程序的源代码,修改方法只能采用比较极端的修改可执行文件的方法了,即所谓的逆向工程。
0 t. z9 j. L5 C2 O4 T6 z2 B: u
于是操起常用的调试工具Ollydbg开始调试游戏。经过2天的不懈努力,终于找到了显示字库的函数,以下列出读取字符的函数部分代码:
- n1 k8 n2 y# |' k$ U: r, [: w% I7 z2 E  T$ A# M
004AA909   8A08          mov cl,byte ptr ds:[eax]        * s0 J* \: A1 ^

, y5 z4 {" [9 ]1 H3 Q$ K004AA90B   40            inc eax                                                                       - y: [7 w* ?+ X% R! V- E
  ?, w( Z4 `/ k- ?
004AA90C  8BF1           mov esi,ecx                     
- G* `+ \: P( T/ A0 u5 o0 N8 h$ c3 p, J  y- |! l) A" ?5 f
004AA90E  8BD6           mov edx,esi                     6 k6 C) M; j- ?5 J
) Q) E2 a+ F5 G; F5 Y2 w
004AA910  F7DA           neg edx                        
7 y) h; L  @1 W5 C" O+ O8 x# A
* _. x: e. `: @8 D( \004AA912  1BD2           sbb edx,edx                     + @0 j9 O% C2 M4 J0 D5 S

3 E: b1 ?, W6 T2 t004AA914  23D0           and edx,eax                     " H# x; B& z1 T2 P( p, E5 u6 p" Y5 W
' t) Q/ T, `+ y8 L' V& z% G8 I
004AA916  85F6           test esi,esi                    
* Y. H  r! k1 r8 U
% o4 t- |0 {( _; w2 N004AA918  8917           mov dword ptr ds:[edi],edx      1 K8 u( N/ [2 K6 p& u1 k  b: P2 U
  d% o: i& ~; l' G+ c0 a5 M( S
  
/ p2 U7 [7 s4 @2 l9 v" S0 D
7 z3 {& r: ]% e/ u% b; d函数开始Eax指向脚本文件grim.tab文件中某行脚本的第一个字符。例如主菜单”Control Help”中的C位置。004AA909一行的意图很明显,读取字符串中当前位置的的一个字符的ASCII码到放到cl中,然后Eax加一,指向下一个字符。然后会将此cl中的字符当作参数,调用另外一个显示字符的函数,完成读取字库文件并显示字符到屏幕的功能。
7 r7 G- e2 g! X- f& X6 W* \. w3 ]' B
我们需要对此部分做改造。如当前Eax指向一个英文字符,则还沿用程序原来的部分,读取一个字节到cl,并使Eax增一;如当前Eax指向一个中文汉字,则需要程序读取2个字节到cx中,并使Eax增二,指向下一个字符的正确位置。那么如何判断当前Eax指向的是一个英文字符还是中文汉字呢,GB2312汉字的编码有一个的特性:两个字节编码最高位(第8位)一定是1。每次读取字符时,先判断第8位是0还是1,如果是1一定是中文,是0则是英文。
& Q4 K1 m, ]/ S3 }: P' {1 A2 F) _2 _
有了思路,对读取字符的函数做如下修改,红色为新增代码: ; g7 M4 L& L* O6 H* U

4 M9 M* F; O- P004AA909       8A08         mov cl,byte ptr ds:[eax]  7 Y  u8 s0 O" m( s4 P4 J
) n& b( R+ u0 {2 {8 q+ D# U
004AA90B       40            inc eax                    
5 B1 Z) P: y' H( R% p
+ S" |$ {5 w* {  i" M+ y1 q                      f6c180       test cl,80h               ! q* U6 B+ i, x1 c+ N

4 F/ v6 N% ?  r7 J* h4 F                     7406           je 4aa90c                 & M7 n: T# {6 I( L4 _- {

7 x6 \& m% z% q! _! d0 s                     c1e108       shl ecx,08h               6 N  W) _$ y. B7 l2 y1 x# q

3 S& E& M4 H6 e                      8a08          mov cl,byte ptr ds:[eax]  . g+ b4 }/ x. ~& l  a

9 W. `5 `5 P' a  N                      40              inc eax                           
' v6 [) I' J8 y  y) e( s       004AA90C     8BF1           mov esi,ecx                " `: R/ d1 N" x1 Y7 e5 o
5 Y& e4 `1 O. X& _+ m+ i. a9 H
004AA90E     8BD6           mov edx,esi               + }& n& @7 L2 [1 G4 C
: A$ e" b2 g6 i) V2 [+ q( i
004AA910     F7DA           neg edx                   5 r1 I, ], L5 R
+ k: G' e- F) L3 n: A
004AA912     1BD2           sbb edx,edx               
2 ?8 ~! R# P% [$ E! j" c% G2 O7 @* ]" \
004AA914     23D0           and edx,eax               $ _/ _- a% w2 h# o+ k* B
% ^% r0 n8 v2 U7 \
004AA916     85F6           test esi,esi              
- V* H+ q/ v# ^% t7 ]: L& H3 R+ E7 s) ^* r3 S5 a+ R& _. F
004AA918     8917           mov dword ptr ds:[edi],edx
+ O3 e0 u- T8 c' M
" B+ _; K  b$ s+ Q  
9 S* r7 H2 t" r3 X9 |- z" _! E; N3 p
先放Eax一个字节到cl中,然后判断cl的第8位是否为1,如果是0,说明是英文字符,则按程序原来的进度跳转到004AA90C这行的代码继续执行。如果是1,则要将cl向左移8位,为汉字第二个字节留下位置,然后再取一次Eax的值,把第二个字节放到cl中。最后Eax增一(Eax增了两次1)。此时Ecx的数值正是一个汉字两个字节的内码。Finish!   ~+ ?7 `0 v& m( w/ g
& L6 }5 }$ U( ]. V
然后用Uedit打开可执行文件,找到一段nop(90)比较多的位置,最后将红色部分的机器码加到合适位置就OK了。
; ?8 ?& ?$ F. E) o. r. d+ X
/ C9 j/ V0 |; Y0 q; N3 Y原贴地址: S- p0 E4 J, u% R* N3 s# l
http://www.cnblogs.com/pscj/archive/2005/05/10/152760.html




欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/) Powered by Discuz! X3.2