设为首页收藏本站官方微博

汉化教程 【转】DirectX 9 游戏汉化详解

[复制链接]
查看: 3064|回复: 3
打印 上一主题 下一主题

[汉化教程] 【转】DirectX 9 游戏汉化详解

跳转到指定楼层
楼主
发表于 2011-1-30 14:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

【转】DirectX 9 游戏汉化详解

本帖最后由 shane007 于 2011-1-30 14:13 编辑 2 P1 Y' w- [* @, \8 `2 t  q8 }8 q9 \
2 J3 e' h6 B5 @8 q7 f
作 者: noword_forever$ E4 G. P( g, W6 R
时 间: 2010-05-25,14:52:51
. u1 c2 g! G% G( G: C4 _, J) S- d链 接: http://bbs.pediy.com/showthread.php?t=113739, V. f; q% u3 p( N+ j
. J' u  K5 }' d% i- I
【文章标题】: DirectX 9 游戏汉化详解
; w7 D2 B  P( I$ E) D4 Y【文章作者】: noword$ m7 n! e, d5 R/ z: v2 L- S
【软件名称】: 无厘头太空战役/ v) N; w  ]& o: q' N
【下载地址】: http://www.verycd.com/topics/2819995// n+ M  V. U! ^5 }# B3 K* L
--------------------------------------------------------------------------------
3 y3 W  t. v9 a) r  【前言】6 h" m( Q! z" e$ _" X
  先copy一段此游戏介绍:9 B/ L. S5 Y9 c9 ]/ q$ o3 ^. B
  
) `" o, A( R3 ]# A! p* d  这是一个独特的战略游戏,具有即时战略与塔防的混合风格,玩家将扮演庞大太空舰队的最高指挥官,你可以自定飞船的构造,摆放飞船的位置,下达命令,然后观看绚丽的射击与爆炸。移动和爆炸时会有动态模糊效果。支持自定义地图。
; ?( [- \2 a  U7 w$ S  
" ?7 d* t/ j7 N# L, s9 ~& T3 W# d  想玩中文版,两个游戏论坛,3DM和YX上,都有人说要汉化,等了几个月,没有下文,说是技术原因。于是决定自己来试试看。
- j# o2 o" X% w* v  
( x/ \! |; g6 y3 p0 j  
3 W5 ]1 k+ v5 s  v. k9 J. ]  【困难何在】
5 F- Z( J; o: J& @; B( y  此游戏的文本都在data目录下,都是明文的文本文件。修改data\strings.ini,将: n8 ~, q0 C2 z5 _3 i; u) F
  
9 c" c8 ~- J, M# D- }% |代码:
1 C1 \. T* t+ B! p  MAINMENU_QUIT        = "Exit"8 T% o- U; e% e% o; ^% t- F4 H
  
' q2 x# E3 K4 e, A  改成/ V: G1 C" A9 ~  t$ L1 ]
  - C3 v" Q7 s) |6 N) N. p
代码:9 F& v& r9 o- V& F
  MAINMENU_QUIT        = "退出"
% z5 |, C5 P+ |$ a; ~% F  0 J1 V, x) J' j/ Y
  2 ]" V- f4 w2 X  @
  进入游戏后,不出所料,无法显示此中文。5 q6 A0 q, b. r8 t" j' H
  8 R4 ^) @1 j. P9 q% N/ t
  茫茫多的游戏爱好者,在尝试汉化某款自己心仪的游戏时,都是死在了这一步——找了半天文本资源,然后翻成中文,满心欢喜和期待的进入游戏,面对的却是一堆乱码或一片空白。满腔热情,化为乌有,无可奈何,黯然神伤。
7 h0 ^. x, A* o+ b/ ~9 L3 @: G  
- j! Y8 [' D0 i$ ~, T  本文的目的,就是希望能够帮助这些有志于游戏汉化的同学,主要介绍了如何让一个英文的游戏,能够正确的显示出中文。) g; a6 y. o& ]( K: \5 ^
  " J4 o3 |: D, T/ |
  ) ]. z5 d6 j, z3 b; _- |
  【调试分析】
- ^) _. c+ w* b9 h  DirectX 9游戏的启动流程是这样的,先执行Direct3DCreate9,返回值是一个IDirect3D9句柄,然后执行IDirect3D9->CreateDevice,得到IDirect3DDevice9句柄。
+ W% @: f; G  D/ u% H  有了IDirect3DDevice9就能使用DirectX 9的一切绘图手段,而我们最关心的就是能够使用D3DXCreateFont来创建ID3DXFont,继而能够非常方便快捷的在游戏中显示文字。& J: ]5 B$ ^1 S6 H) C- O  x3 A2 Z
  ; w' q. p" Z$ w
  用ODBG载入游戏的exe文件,“查找所有模块间的调用”,找“d3d9.Direct3DCreate9”:
8 w6 b6 j1 r5 Z$ `+ e( c- O  
9 s5 y6 M; L' y4 c: C代码:
9 A$ @/ l( w5 z6 q7 [9 S* D+ h) Z  00501974   .  BB 500A5400        mov     ebx, 00540A50                   ;  ASCII "Initialising 3D Engine"! e/ u' R6 Z9 a& B
  00501979   .  E8 22130000        call    00502CA0* d- r  g+ p- Q* b+ t: x
  0050197E   .  6A 20              push    206 L6 _. Q# I3 |% Z5 }5 ]  g# k8 U
  00501980   .  8977 18            mov     dword ptr [edi+18], esi
: e4 e. v, a: D  Z  00501983   .  E8 2E8B0100        call    <jmp.&d3d9.Direct3DCreate9>* b2 U0 {7 u0 t9 g/ X6 h
  00501988   .  85C0               test    eax, eax  C8 N+ Z, P, P2 Z* A5 Q
  0050198A   .  8947 10            mov     dword ptr [edi+10], eax         ;  edi+10 = 58d550
5 B" P" x  ^. Z! u  7 I' I2 Z& x' I' x$ v* Z; y3 Y
  往下找,就能找到IDirect3D9->CreateDevice:6 d- T  H8 a( B- g  D/ Q
  
/ o4 [# C2 E' N3 p, T9 P代码:
9 s+ i# Q: B. f, q# T; ]. O5 d  00501B4C   .  8D77 14            lea     esi, dword ptr [edi+14]
' x8 o* ~/ P& u$ F; T  00501B4F   .  56                 push    esi                              ;  58d554  => IDirect3DDevice9
; a; l) `  y( n' P5 K' H  00501B50   .  8D4F 40            lea     ecx, dword ptr [edi+40]1 `& l: Q/ W! P
  00501B53   .  51                 push    ecx
4 g* Z9 P1 Z) o. p  00501B54   .  6A 40              push    402 ^" W! M* e3 U. H
  00501B56   .  EB 14              jmp     short 00501B6C
1 j3 j( T2 f2 f7 D) g, H  l8 x- I  ...
/ t) e" O- `' ^9 f+ w) g  00501B6C   >  8B4F 18            mov     ecx, dword ptr [edi+18]$ W3 g+ ~* E8 k3 F* q  M+ j+ [
  00501B6F   .  8B47 10            mov     eax, dword ptr [edi+10]
$ l$ W1 u# V2 c9 j0 i/ c2 s  00501B72   .  8B10               mov     edx, dword ptr [eax]9 Q7 U9 D& a% e$ g( ]. D
  00501B74   .  8B52 40            mov     edx, dword ptr [edx+40]  q7 X' ?! ~9 f3 f% t5 I# G
  00501B77   .  51                 push    ecx
  h: ^2 N7 d& l) I: o  00501B78   .  8B4C24 24          mov     ecx, dword ptr [esp+24]( j* D* x  [- }. x- O/ A! S
  00501B7C   .  51                 push    ecx
; ~6 T) ?" U& m6 ~  00501B7D   .  55                 push    ebp5 Q# [# i$ A, y1 h1 u8 j9 \
  00501B7E   .  50                 push    eax0 C: B# p( O4 W+ |
  00501B7F   .  FFD2               call    edx                             ;  IDirect3D9::CreateDevice
  U8 t( X! h% T0 G  
, _) g0 g' E! j: [8 W  
3 M) k% M3 Y0 p' m7 j3 `, f  由于是所谓的COM接口,没有十分明显的标志,不是很好找。
: c7 O0 K5 a  S& v% F6 o1 d  
2 x! Y4 b! i# a9 d7 x  在微软的DirectX SDK d3d9.h文件中,IDirect3D9的接口是这样的:
$ Q6 ^4 ~8 V& d# b( e8 h* c  ; r- a* [+ _; i" i# R
  
2 K+ i) ^. z6 j/ [" w代码:
& P$ M( F- R( B/ g! Q  DECLARE_INTERFACE_(IDirect3D9, IUnknown)
. v# m2 ]5 j% _. \! n3 |* f$ R, v  {
5 H, i6 O# J: O& c! n      /*** IUnknown methods ***/; ~& r# n% R- V. n9 L5 a
      STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
, Q* n3 q' J- L      STDMETHOD_(ULONG,AddRef)(THIS) PURE;
. W- R8 h& z/ G4 G  ?1 ?: J      STDMETHOD_(ULONG,Release)(THIS) PURE;3 T  f- j0 t8 b9 ]; W5 c$ w7 P
  
. W; M3 V$ q8 u      /*** IDirect3D9 methods ***/
6 t* |! [1 \. {( l% y" A      STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;  k! j6 x1 I7 M* t
      STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
$ e, F; f  e. H" l( j      STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;
' Y. z" n0 s' H; K. ?( M      STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format) PURE;6 B7 ^, ~0 @" C# B- j
      STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE;
0 \: N+ n1 V, |7 n2 n3 I      STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter,D3DDISPLAYMODE* pMode) PURE;
# D2 @; [& L4 l+ M& h: U      STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed) PURE;7 A) L* S' M! r
      STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat) PURE;
; @1 i; M) q: c      STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels) PURE;9 f) O: F5 a( u( `% n- x6 b0 W8 t
      STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE;$ V2 {  b1 b5 \$ J# K0 |
      STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat) PURE;* F" c, F% C* y- ^8 |4 B
      STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps) PURE;
) b  m% _' G' Q' [3 J' d- o      STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;
9 S0 P8 x; G- V  s8 v5 c9 t. I      STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface) PURE;
0 f! K; C6 k, h- R# z% m& a      
2 {: f% x1 U; Z; d: G/ C      #ifdef D3D_DEBUG_INFO
1 `0 j+ q9 \( I+ Z      LPCWSTR Version;  I& t6 f" f5 d4 s7 d1 ?
      #endif% X( n  s! F4 ]7 q- S
  };
" b$ I8 u. f' v8 p3 B8 s2 F  7 ?* j! G# h5 X# Y
  
, D# t. t0 ]! C  B  e  CreateDevice是第17个函数,所以它的地址是(17-1)*4 = 0x40,4 o! K$ f8 ^7 C/ d
  00501B74   .  8B52 40            mov     edx, dword ptr [edx+40]; ^6 C: E$ k. u  z% [0 A
  这里的edx+40就是这么来的。
2 f  }8 m" j* j. V9 ^  + N* O( s/ {- G! o
  如果觉得算起来很麻烦的话,还有一个简单的方法,可以自己编译一个d3d9的程序,然后反汇编看看。
$ \- |# @. C3 g/ {5 Q5 ~; z  
4 t( n* O( d/ ^! B) Y; g  如果还觉得麻烦,还有个更简单的方法,直接往下找,通常会有一些调试文本能够帮助定位,例如:1 i5 Q8 k" B, ^! [8 j
  00501B86   .  BB 600B5400        mov     ebx, 00540B60                   ;  ASCII "CreateDevice"$ D9 {7 h4 Z# P- G6 F, n
  ...
& E" I" N$ p+ i7 l1 n; y  00501BBB   .  BB 700B5400        mov     ebx, 00540B70                   ;  ASCII "CreateDevice failed again"0 M" _% b1 G( @- o% p
  当然,这个办法并不通用,有效与否完全要看游戏作者的脸色。- h; A" a) {$ L9 l8 Q$ o  A4 d2 [
  - M9 }0 L; U/ d2 j2 g* |; Q
  知道了IDirect3DDevice9的地址,就能植入我们自己的初始化ID3DXFont的代码。
! h2 \4 w# c; |3 L; y8 R1 G  8 R+ f0 G. {# F
  有了ID3DXFont,下面就是要找到用于显示文字的函数,并用我们自己的代码来替换实现。
. }! g) E2 k( ~7 J3 |  
5 Y% J+ Q* w& e" w2 _  随便找一段游戏中出现的文字,比如开始菜单上出现的“Full 1.37”,ALT-M,进入内存窗口,在所有搜到的该字符串上下“内存访问”断点,最终会找到地址在4FFF50的一个函数。
- Y9 \/ t9 f" B3 s  ) ^( f, A' z% \7 ^5 N4 h
  该函数返回时,用的是“retn 14”,在4FFF50处用“retn 14”改写,切回到游戏后没有任何字符出现,说明这个函数正是用来显示字符的。
: A/ s0 H- E- g$ y' w. F  4 o" W: k# ]) x1 Q! [7 u' `& `5 ~
  原谅我在这里对于怎么找到4FFF50的过程含糊其辞,一笔带过了。确实没有什么取巧的方法,完全取决于破解的功力,良好的耐力,以及一点点好运气。而这也正是游戏汉化的难点所在。% A) ?; F2 a' g; y6 I" g
  ; R, y$ R4 H" P% X
  找到字符串显示的函数后,还要弄清楚该函数的接口。
( r5 p6 R5 O4 e  ' i- P. [2 A* U& ^# ^  d
  在屏幕上显示一个字符串,通常需要知道这些要素:字符串、显示的位置(X,Y坐标)、颜色、字符的大小,以及一些flag用于表示左对齐,右对齐,居中,加粗,倾斜等。
9 R: u" A7 v7 ?" D6 x+ T- n  
' q; O& w: G' z  F  前面说过,返回用的是“retn 14”,说明栈里有20(10进制的14h)/4=5个参数,当进入该函数时,栈上的数据是这样的:& ~- t/ \6 I6 f  a
  
% ?. y# q( a7 ~* i  q8 _' l: h代码:
  W; V! T% G( K/ O  0012FE84   00453C48  返回到 GSB_1_37.00453C48 来自 GSB_1_37.004FFF504 l" k3 e" z! {, H' O$ Z$ O( ^
  0012FE88   0012FEB8  ASCII "Full 1.37"; [' t& y+ k- C) x/ K
  0012FE8C   00000000) i0 m8 X) E5 f$ B* b
  0012FE90   40400000
) M0 p, ^( }# n: N$ Z  K5 W$ A  0012FE94   FFFFFFFF
) D. y- m9 a0 T$ H& _  0012FE98   447D8000
0 f8 c2 }! b9 L3 v% s  ( L+ A$ h1 `# t& i
  第一个,很明显就是要显示的字符串,后面几个是什么玩意儿呢?
  G4 v# [' K5 j3 M( g5 q0 `8 s  
+ h$ ?5 u6 M$ A2 |+ }( W. A0 U  回到调用004FFF50的地方,在00453C1D下断点:
' n. F. A' a' l- n6 ?  2 X, ]9 ~2 ^, L+ b0 B5 ?
代码:
: W& {- T& E# N' F$ F, Y  00453C1D  |> \D94424 14          fld     dword ptr [esp+14]
. h: w8 s8 |# j* Y: V$ j- r  00453C21  |.  51                 push    ecx
6 {. m9 W# A4 H- J) i5 e  00453C22  |.  D91C24             fstp    dword ptr [esp]                  ;  参数5  1024.04 q# I+ ^( D' z9 m: O" j4 E( o
  00453C25  |.  6A FF              push    -1                               ;  参数4
/ }0 J5 W, A" v  00453C27  |.  D905 F4125400      fld     dword ptr [5412F4]
# [- F- X4 R, @3 a6 T  00453C2D  |.  83EC 08            sub     esp, 8
3 V( ~: v/ N8 X/ K. j* H, c  00453C30  |.  D95C24 04          fstp    dword ptr [esp+4]                ;  参数3  3.07 o+ n1 i4 |7 Q
  00453C34  |.  8BD0               mov     edx, eax
4 C" c  P' ?  |" Q9 y/ H  00453C36  |.  D9EE               fldz
6 u. S8 B! {4 N7 E* V: j; |5 f  00453C38  |.  D91C24             fstp    dword ptr [esp]                  ;  参数2  0.0# O4 w3 N& S  S
  00453C3B  |.  56                 push    esi                              ;  参数1
5 ^% k& x( {/ }" h/ [  00453C3C  |.  BE 01000000        mov     esi, 1
8 i% E$ @8 x' D( p5 o4 \3 l% D) l  00453C41  |.  8BCE               mov     ecx, esi  ^' ]: H' w( o' E
  00453C43  |.  E8 08C30A00        call    004FFF50' l5 K4 R$ s0 |" S
  6 K, ]( n9 i6 |1 }
  
) @, P* y- V* [2 w1 j; ^1 w. T  可以看到,参数4是一个固定值,第二、三、五参数都是浮点数。
+ v( g9 I, H: c& V  
/ j. n% ?' G1 L7 d/ @  这里有一个技巧,在函数开始的地方修改参数的值,看看会发生什么变化,很快就能知道参数的作用。
5 W2 ?! r% _! t' M  4 n2 W. z6 f7 G' W& g
  参数4是颜色值,Alpha和RGB值都是FF,就是白色,与在游戏中看到的字符颜色相同。
3 \! U$ ^' d5 _9 l8 o  参数2是X坐标,参数3是Y坐标,参数5用于调整。
- O& }2 J& q' e6 N# V& `  需要注意的是,还有两个参数是通过寄存器ECX和EDX传递的,ECX用于表示左对齐(0),右对齐(1)和居中(2),EDX是固定值58D6D0,一个全局的结构或类。9 p% `& x4 w% p+ e
  
. \3 u3 ?6 h8 f+ f; H7 L; F$ I  此游戏有两种字体,因此用于显示字符的几大要素,现在还缺一个,就是不知道如何判断字符的大小。
( W9 U) x5 F7 X% i  
: a* i& w& d6 [+ }, w7 C1 x  在用于显示文字的004FFF50的上下断点,多跟几次,就会发现,每次调用以前,都会调用一个call:- G  ~0 x9 O- {) t4 J$ B; ?" r' V
  8 A  Y5 F) Q! L% S) M, E1 ?
代码:; B2 Y; H6 X" x: a2 y/ L
  00453BD5  |.  BE 44035300        mov     esi, 00530344                    ;  ASCII "zekton16.dds"7 J* c& t$ W0 v* w4 _: ^7 D
  00453BDA  |.  E8 91B50A00        call    004FF1708 a" r& ]. t+ w( S
  
' \! f' ?6 W. ~$ n" {0 T8 U/ d" I  004479E7  |.  BE 54035300        mov     esi, 00530354                    ;  ASCII "cwfont20.dds"
- k$ P: O" w3 _: U0 L4 ~  004479EC  |.  E8 7F770B00        call    004FF170& {) H' A" w3 J$ e
  
8 E* m* q2 G8 S' @! O  在游戏目录data\font下面有两个文件zekton16.dds.dat和cwfont20.dds.dat,由此判断004FF170应该是用于选择字体的函数。/ S8 f  h# V* Z+ N
  
3 s- B% U: y' t: N  总结一下:
' A- p$ O- U; V) E  第一步,找到IDirect3DDevice9句柄,用于初始化ID3DXFont。# T  E# i/ l/ q2 q* u$ j# K; n3 o
  第二步,找到显示文字的函数,用自己的代码实现之。& c3 ?4 w* ~* V4 U. `
  第三步,逐步找到其他需要修改的地方,比如用于得到字符串宽度、高度,指定宽度的字符串换行显示等函数。) ?5 ]5 b9 v# o
  & x# T& f/ w. k$ V$ K: p1 V
  + w3 N8 F0 L# H! \! V3 z
  【具体实现】) N8 M0 ?: n* p$ V' }4 q
  我用的是注入dll,然后打内存补丁的方式。这样的好处是便于更新,可以任意修改实现过程,以后游戏出了新版本,也只要修改几个地址变量,重新编译一下就可以了。+ k8 q7 l4 A. K, M; \! D5 {
  另外一个好处是,不以文件补丁的形式发布,没有版权问题。(有人关心这个吗?)- q( ^2 y) U% {. j' [* n: T1 ~! p
  
; v) F  _& a3 W% [  源码在这里:
6 M" K: ?9 W$ ^/ y8 v5 G3 v5 V  http://gsbzhcn.googlecode.com/svn/trunk/src7 `( T1 p% `" P, Y
  
4 D7 F/ o6 {' ]) {; i9 A  简单的介绍一下流程:6 t& o2 X$ ~$ S8 z# }5 S
  1.CreateProcess启动游戏的exe,并使之处于挂起状态。
; U% m$ Z% j! c& v3 s, A5 z  2.VirtualAllocEx在游戏进程上申请一块内存,WriteProcessMemory往里写入要注入的dll名称。
' X' Q9 u/ G2 u' G' v  3.GetProcAddress得到LoadLibraryA的地址。* \. c+ U9 k* c! B! O& h3 y0 @3 h3 r
  4.CreateRemoteThread运行LoadLibraryA,注入dll,dll载入时会为游戏进程打上补丁。( f( p3 w9 O2 `& D  k( T
  6.WaitForSingleObject等候dll载入完成。
3 c% W' b$ y4 ?4 S3 M8 [4 V  7.VirtualFreeEx清理掉之前申请的内存。
" m% @- x" ]0 c0 J: S  q  8.ResumeThread让打过补丁的游戏进程运行起来。
1 Q" @  y# |1 q0 e2 R0 A- N; S  
3 e  `& f9 _: c& D  {  内存补丁主要是让游戏在关键的地方跳转到我们的dll,执行一段代码后再跳回去,或者直接用dll里的函数代替之。
8 @# _) Z8 E) i9 N, ]  
8 _4 p3 j! d* @! G( U6 S  
( l  i$ g- M8 s" p* E( o  【结尾】5 T2 L& D! B, ~% W  e0 c: P4 w
  此游戏的汉化正在http://code.google.com/p/gsbzhcn/ 进行,文本不多,奈何翻译人手也不多,希望有兴趣的同学能够参与。1 }4 T4 g* d+ y0 Y9 W) W" K. ~
  
# F9 ?  R, Y5 R$ J--------------------------------------------------------------------------------* i' i3 V, h% ?9 X4 n: h5 Z
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!% _  I) v" t: h  u& O
; P" W1 ?  T" v; y
                                                       2010年05月25日 14:52:11
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
发表于 2011-2-6 20:47 | 只看该作者
楼主忒牛了
回复 支持 反对

使用道具 举报

板凳
发表于 2011-3-10 15:19 | 只看该作者
高手啊,仰望。
回复 支持 反对

使用道具 举报

笨蛋狐狸 该用户已被删除
地板
发表于 2011-3-11 10:19 | 只看该作者
仰慕,学习了,也感谢007的转载。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

冒险解谜游戏中文网 ChinaAVG

官方微博官方微信号小黑屋 微信玩家群  

(C) ChinaAVG 2004 - 2019 All Right Reserved. Powered by Discuz! X3.2
辽ICP备11008827号 | 桂公网安备 45010702000051号

冒险,与你同在。 冒险解谜游戏中文网ChinaAVG诞生于2004年9月9日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

快速回复 返回顶部 返回列表