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

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

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

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

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

【转】DirectX 9 游戏汉化详解

本帖最后由 shane007 于 2011-1-30 14:13 编辑 1 }+ K+ `' l9 Z8 R  i

8 F  d8 m# G/ k( f6 X& @作 者: noword_forever
8 y  Y& B; W+ B- |: ]; }9 E6 o时 间: 2010-05-25,14:52:51
6 w# E' G0 Q: f5 ?* J链 接: http://bbs.pediy.com/showthread.php?t=113739; I% _$ l" `2 [* s% d
% M- ]) [$ R( v. }' C
【文章标题】: DirectX 9 游戏汉化详解
# x3 ]8 b! I- H. r【文章作者】: noword
& {1 e' E$ ?, n! M【软件名称】: 无厘头太空战役
# e9 d9 X8 F- `  ^8 R+ M【下载地址】: http://www.verycd.com/topics/2819995/% @: j+ f5 M8 o' s( ?2 {: K
--------------------------------------------------------------------------------- t2 ~4 ]( r* q, V" H
  【前言】6 I) ^9 t- Y9 V9 X- P" p* r
  先copy一段此游戏介绍:
% O" K- y) }" Y1 n  3 M0 m( a! \2 L" v2 [
  这是一个独特的战略游戏,具有即时战略与塔防的混合风格,玩家将扮演庞大太空舰队的最高指挥官,你可以自定飞船的构造,摆放飞船的位置,下达命令,然后观看绚丽的射击与爆炸。移动和爆炸时会有动态模糊效果。支持自定义地图。
  u2 M9 b; Z9 u1 H  
- e+ G# |: A* B$ T# j- b  想玩中文版,两个游戏论坛,3DM和YX上,都有人说要汉化,等了几个月,没有下文,说是技术原因。于是决定自己来试试看。
" ~' M. }. P4 t  z. A7 A0 Z  h, t  1 j; [3 m3 F7 ]* F6 ~8 q
  
% }; u/ Q  f, _+ O! c2 A+ c% g$ D  【困难何在】
# _! S- e+ u# o0 z- b" _+ }  此游戏的文本都在data目录下,都是明文的文本文件。修改data\strings.ini,将
+ Z; C* C* x2 Y: \; u" S  - [  Y+ M( Y0 ?( y
代码:1 H3 [3 ]) ]- u* Y5 W) N
  MAINMENU_QUIT        = "Exit"
5 f6 Q: ]/ i5 K& _4 l3 Z  
& o$ _3 t/ r1 \4 @) s. B  改成
. g$ E6 e# ]1 X  M  9 G6 E6 O+ m4 B: N& l
代码:
9 J1 c. K& {) H* e7 ?' }& C  MAINMENU_QUIT        = "退出"
3 b' U! P/ O3 z0 ^. u$ l  / _9 h1 F2 q- D1 h) @- _2 B
  ( C2 q7 e( P+ R7 w" w/ O3 ]
  进入游戏后,不出所料,无法显示此中文。
# r7 q5 L3 r8 }. R9 a  
/ }9 @: `  [$ j3 x  茫茫多的游戏爱好者,在尝试汉化某款自己心仪的游戏时,都是死在了这一步——找了半天文本资源,然后翻成中文,满心欢喜和期待的进入游戏,面对的却是一堆乱码或一片空白。满腔热情,化为乌有,无可奈何,黯然神伤。
. X4 e7 w, D5 u. m6 }, @, a# w9 K  
2 v7 n' K: u) Y3 }5 M  本文的目的,就是希望能够帮助这些有志于游戏汉化的同学,主要介绍了如何让一个英文的游戏,能够正确的显示出中文。
9 r- o2 y! B) Y% z  # t" D$ @, K5 |0 Z5 g  l
  % k0 ?8 I/ O: T5 W/ v
  【调试分析】
0 `% G; E* G. N; c4 X  DirectX 9游戏的启动流程是这样的,先执行Direct3DCreate9,返回值是一个IDirect3D9句柄,然后执行IDirect3D9->CreateDevice,得到IDirect3DDevice9句柄。
; Z4 ?  D' m0 F: X4 u  有了IDirect3DDevice9就能使用DirectX 9的一切绘图手段,而我们最关心的就是能够使用D3DXCreateFont来创建ID3DXFont,继而能够非常方便快捷的在游戏中显示文字。" A  j! @4 Z! q9 f2 c+ w2 e1 o
  
( x1 O; i- V/ y' ]  用ODBG载入游戏的exe文件,“查找所有模块间的调用”,找“d3d9.Direct3DCreate9”:* P( W3 @* ]6 e1 q6 N; ?% R
  ! W7 H6 l' J, M" G) w
代码:
4 @& r* T/ ^3 X1 J: L# c, e  00501974   .  BB 500A5400        mov     ebx, 00540A50                   ;  ASCII "Initialising 3D Engine"
1 k3 Q' B* P& O, ]) m! F# h5 Q% \  00501979   .  E8 22130000        call    00502CA0; U0 {/ y; n& j" L5 t* v( g
  0050197E   .  6A 20              push    20
9 E: i, [6 J6 j+ `5 y0 k! Z8 U7 Z  00501980   .  8977 18            mov     dword ptr [edi+18], esi+ r7 k* E* P1 A/ z/ h
  00501983   .  E8 2E8B0100        call    <jmp.&d3d9.Direct3DCreate9>
6 E* b+ L  U6 p+ D7 f  00501988   .  85C0               test    eax, eax
: Y& \0 V" I6 H$ F3 r! x  0050198A   .  8947 10            mov     dword ptr [edi+10], eax         ;  edi+10 = 58d550
4 r" j) T% ^' S5 F) N  
( |  i/ R) T* `) v& K+ q2 m5 X1 f1 G  往下找,就能找到IDirect3D9->CreateDevice:
" e( t: y5 c0 S( ?, y  
) f( @% E  Q% i  Z/ d& h代码:' [0 w8 Z' P  z5 q$ W
  00501B4C   .  8D77 14            lea     esi, dword ptr [edi+14]
/ G1 Y; V, b8 ]3 Z  00501B4F   .  56                 push    esi                              ;  58d554  => IDirect3DDevice9
# W$ s; a+ e1 l. r+ j( w! d  00501B50   .  8D4F 40            lea     ecx, dword ptr [edi+40]$ @" q# L- c+ {3 b5 \* T$ D+ C& A
  00501B53   .  51                 push    ecx
9 r& f# p. [( O9 v) A, m8 A/ H7 c$ N  00501B54   .  6A 40              push    40
2 o* T4 A, L0 m* W  00501B56   .  EB 14              jmp     short 00501B6C
2 {* ]. p+ o8 w1 D5 I; k+ f  ...8 Y8 X: ^. N. w* h3 N
  00501B6C   >  8B4F 18            mov     ecx, dword ptr [edi+18]6 K; {) h5 _1 h2 ^
  00501B6F   .  8B47 10            mov     eax, dword ptr [edi+10]8 T& q) f2 ~( Y$ r# F
  00501B72   .  8B10               mov     edx, dword ptr [eax]6 A0 W! S7 y0 q
  00501B74   .  8B52 40            mov     edx, dword ptr [edx+40]( E! o9 l- E( S7 h, F, c# p
  00501B77   .  51                 push    ecx
; a4 @2 G) G4 S) i, p" a  00501B78   .  8B4C24 24          mov     ecx, dword ptr [esp+24]3 \( P. M0 }; Z, [: q3 a5 y
  00501B7C   .  51                 push    ecx
  _% h  u  y: A1 l. l  00501B7D   .  55                 push    ebp) \& h! k! ?4 J0 [6 e
  00501B7E   .  50                 push    eax
" f" V' {, q# f  z+ ^, I; Q9 L+ J  00501B7F   .  FFD2               call    edx                             ;  IDirect3D9::CreateDevice
3 u, i3 h* \$ @8 Y" `  i  
; i0 C3 u+ ~* f1 D2 R  * o. O) [% |* [; p. X8 E
  由于是所谓的COM接口,没有十分明显的标志,不是很好找。
( k: K! x6 k2 G  # I. j2 `) `- @( Z3 ~  r* D
  在微软的DirectX SDK d3d9.h文件中,IDirect3D9的接口是这样的:
2 `3 a; Z4 s- {3 @8 o  & [* l8 M% L1 `/ h7 w/ k+ \
  ) E3 L. |5 ]' _) L) D' A
代码:% s; c1 G9 P4 r& T
  DECLARE_INTERFACE_(IDirect3D9, IUnknown)
- F7 i0 i% [5 ?2 r  {
  C( T# n# e; m2 B$ K      /*** IUnknown methods ***/" x+ O& h- x+ m/ }8 q5 {: z& D9 D
      STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
9 m$ m% y3 [3 @      STDMETHOD_(ULONG,AddRef)(THIS) PURE;1 v* W  @" i( T; _- q
      STDMETHOD_(ULONG,Release)(THIS) PURE;2 e* F5 Q" M% i+ @  \5 Z2 A
  3 }( |4 X( y: M- D. M! F1 d% P
      /*** IDirect3D9 methods ***/# {% A" w. K4 p; C0 g
      STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;) C. A1 }3 n/ x/ f/ z
      STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;
1 a/ \4 w5 G+ f. M( x      STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;) p8 V/ f  |5 r. o
      STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format) PURE;6 `# H" a) R% @0 C8 P
      STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE;
3 y' T! H9 [  I1 E( C! I      STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter,D3DDISPLAYMODE* pMode) PURE;
$ `# `8 p5 X1 i2 p  y6 M      STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed) PURE;
2 a, S, k- h8 p6 ^* o, F      STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat) PURE;
1 R* V+ D1 m7 S6 t0 w      STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels) PURE;
% A) y& l" N/ u2 M/ l      STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE;
3 O+ e/ a' {, L      STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat) PURE;6 ]9 q" o3 ?, K0 h, q
      STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps) PURE;7 Z+ h5 {9 i* w3 E
      STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;
0 Q# c5 s; b5 _      STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface) PURE;
3 Q6 B8 P" E# o7 P      
  }7 R3 l5 Z' _      #ifdef D3D_DEBUG_INFO
  `5 ~9 E' U1 d' R      LPCWSTR Version;
9 q7 w( p4 A* B4 H2 |/ u      #endif
* Y+ E" S7 @  J$ D2 g  };) A/ B) ]7 [% }, B. H* c  u8 \
  
& {& D5 f2 b5 b0 Y( B; g  ; z" V  v/ Z( b  r( T# G0 m
  CreateDevice是第17个函数,所以它的地址是(17-1)*4 = 0x40,
, u6 Y* [$ R* G) q8 ]/ b  00501B74   .  8B52 40            mov     edx, dword ptr [edx+40]& c0 r: y& Q( G. Q
  这里的edx+40就是这么来的。
0 B& O" m8 e0 a* s( `( K  % N% n% \9 m- D, c
  如果觉得算起来很麻烦的话,还有一个简单的方法,可以自己编译一个d3d9的程序,然后反汇编看看。( \  p& Q/ k" }2 S' `' U
  4 [1 ?) i0 E/ h
  如果还觉得麻烦,还有个更简单的方法,直接往下找,通常会有一些调试文本能够帮助定位,例如:* K  S  p/ j; w. v
  00501B86   .  BB 600B5400        mov     ebx, 00540B60                   ;  ASCII "CreateDevice"
6 B" H( f9 C5 _% W2 h- |8 i  ...
) c# {- I( h9 i  00501BBB   .  BB 700B5400        mov     ebx, 00540B70                   ;  ASCII "CreateDevice failed again"2 w+ S! \+ j2 v! J, D
  当然,这个办法并不通用,有效与否完全要看游戏作者的脸色。% A9 o% i5 |$ t0 ]( e# {
  % S# j$ m6 q$ {
  知道了IDirect3DDevice9的地址,就能植入我们自己的初始化ID3DXFont的代码。7 ^% {2 @! ~! Y# M: F" _
  & q- \! R& A" B. C8 D1 @; f
  有了ID3DXFont,下面就是要找到用于显示文字的函数,并用我们自己的代码来替换实现。. a( n5 E) x+ T5 N2 U4 _9 w
  - G1 l- O4 p0 u  ^  s
  随便找一段游戏中出现的文字,比如开始菜单上出现的“Full 1.37”,ALT-M,进入内存窗口,在所有搜到的该字符串上下“内存访问”断点,最终会找到地址在4FFF50的一个函数。
! r6 N1 b) f, W& q9 ]! \  
( v0 U: l/ W/ q( f5 m1 J& Q  该函数返回时,用的是“retn 14”,在4FFF50处用“retn 14”改写,切回到游戏后没有任何字符出现,说明这个函数正是用来显示字符的。% x8 r0 w/ I0 b
  
# \( d$ I. O/ n; ^  原谅我在这里对于怎么找到4FFF50的过程含糊其辞,一笔带过了。确实没有什么取巧的方法,完全取决于破解的功力,良好的耐力,以及一点点好运气。而这也正是游戏汉化的难点所在。
) ]; y- h' l9 `( ^7 V( |; [/ m  9 {* r( s. n* D4 V8 X7 A$ F. S( Q
  找到字符串显示的函数后,还要弄清楚该函数的接口。4 _, q* {, p. l5 h
  : b, }; P' [0 B- G" ^' l( ?$ n
  在屏幕上显示一个字符串,通常需要知道这些要素:字符串、显示的位置(X,Y坐标)、颜色、字符的大小,以及一些flag用于表示左对齐,右对齐,居中,加粗,倾斜等。4 a- [1 Q2 R) M2 H6 l
  
! y: K4 [7 {- X6 i! K+ G  前面说过,返回用的是“retn 14”,说明栈里有20(10进制的14h)/4=5个参数,当进入该函数时,栈上的数据是这样的:
5 c, F" [  d) q" A: T) {  * z2 R4 n. E. O2 h, B$ q
代码:+ a; X6 A/ n0 V, d4 R. l
  0012FE84   00453C48  返回到 GSB_1_37.00453C48 来自 GSB_1_37.004FFF50
% M9 T+ }- h# _) @  0012FE88   0012FEB8  ASCII "Full 1.37"
- E3 f3 v8 d3 v, c! E7 H$ E  0012FE8C   000000003 K, p& h6 Y/ ?: m" T8 t
  0012FE90   40400000. o$ w/ v# ?; D$ r
  0012FE94   FFFFFFFF
( y, n& _0 m' v. t' g- A  0012FE98   447D8000( b, F7 Y3 r, \  n3 }
  % [5 g4 q% V  E# f+ j1 d; u7 Q
  第一个,很明显就是要显示的字符串,后面几个是什么玩意儿呢?
0 _  c. c, l; R* Q- A" C# H    |$ B5 [3 h/ v5 t' @
  回到调用004FFF50的地方,在00453C1D下断点:
4 ^& o9 f: A% l- Q, y  - P4 F& {. }* H6 A& n5 ~
代码:
/ J+ O  _) U: f+ L  00453C1D  |> \D94424 14          fld     dword ptr [esp+14]
3 d4 _* M4 T: j7 b  \0 H  00453C21  |.  51                 push    ecx7 v1 ]3 A2 r; c: x  e
  00453C22  |.  D91C24             fstp    dword ptr [esp]                  ;  参数5  1024.0
9 A- V2 Y. ^$ S  R, ?$ I- s! {  00453C25  |.  6A FF              push    -1                               ;  参数4$ `8 T9 ^% P& K
  00453C27  |.  D905 F4125400      fld     dword ptr [5412F4]
0 {- L& x* \# t0 k1 [  00453C2D  |.  83EC 08            sub     esp, 8
6 O, a+ ^9 P' Z6 Z* \  00453C30  |.  D95C24 04          fstp    dword ptr [esp+4]                ;  参数3  3.0
7 W/ j% u, K7 i; C3 A  00453C34  |.  8BD0               mov     edx, eax) _$ t, G& C7 t+ i( w# T! X) [
  00453C36  |.  D9EE               fldz
& ?* Z# I1 d4 H  00453C38  |.  D91C24             fstp    dword ptr [esp]                  ;  参数2  0.0
) [/ Q0 t6 x7 l8 [  00453C3B  |.  56                 push    esi                              ;  参数1
8 @) e  {5 ]# D; o  00453C3C  |.  BE 01000000        mov     esi, 1. H* w" _0 f. t$ G/ @) ?5 R3 ]
  00453C41  |.  8BCE               mov     ecx, esi
% m4 _1 Z, s% `( N" o  00453C43  |.  E8 08C30A00        call    004FFF50/ P+ D( ]: V1 V. x! c
  
+ d4 X( l9 W. j& e# S$ r  
& G7 i9 Q* W* V, U  L9 ~  可以看到,参数4是一个固定值,第二、三、五参数都是浮点数。
: z! K2 G2 c: A- h  2 F! ~6 M8 D; U7 Z
  这里有一个技巧,在函数开始的地方修改参数的值,看看会发生什么变化,很快就能知道参数的作用。
; ^9 _7 }$ G3 @7 X) N  
6 F8 ?8 W+ n% _8 _2 Y( F5 d  参数4是颜色值,Alpha和RGB值都是FF,就是白色,与在游戏中看到的字符颜色相同。
8 _5 I! i6 W. c8 ^5 q9 k. M4 _  参数2是X坐标,参数3是Y坐标,参数5用于调整。& s! v1 ?" s; E
  需要注意的是,还有两个参数是通过寄存器ECX和EDX传递的,ECX用于表示左对齐(0),右对齐(1)和居中(2),EDX是固定值58D6D0,一个全局的结构或类。
: F, z# v5 F! N# y, w0 K  
$ W7 B! q5 k( l8 Y* t  此游戏有两种字体,因此用于显示字符的几大要素,现在还缺一个,就是不知道如何判断字符的大小。
9 B2 g$ y( D' A4 U' p3 d7 y+ w  , v; L! B. J% F/ B5 l6 ^; \( `
  在用于显示文字的004FFF50的上下断点,多跟几次,就会发现,每次调用以前,都会调用一个call:
2 F1 u5 O0 C- r) |8 g9 D  
' R* x# ]. o" K. d代码:
; Q7 i3 ?8 U$ W0 u3 l  00453BD5  |.  BE 44035300        mov     esi, 00530344                    ;  ASCII "zekton16.dds"
0 ~9 C3 N$ I8 J  00453BDA  |.  E8 91B50A00        call    004FF1700 j/ V% I3 _& H4 _& }
  
0 }4 v: D' j; o) O2 I. G  004479E7  |.  BE 54035300        mov     esi, 00530354                    ;  ASCII "cwfont20.dds"3 ~. g8 u( N# L( N& f  b$ \
  004479EC  |.  E8 7F770B00        call    004FF170' D! @4 _4 ]4 ^( Y2 s3 u
  
. X. y8 y' C3 i5 A- ~4 f  在游戏目录data\font下面有两个文件zekton16.dds.dat和cwfont20.dds.dat,由此判断004FF170应该是用于选择字体的函数。9 M  {) L0 k4 {) H: [6 F8 h$ \
  % O" }$ k7 a" b6 L; i
  总结一下:
: j% I* ^3 H+ x8 ?0 u9 T5 R  第一步,找到IDirect3DDevice9句柄,用于初始化ID3DXFont。- F; N7 Y$ m/ @" @' T+ [2 n
  第二步,找到显示文字的函数,用自己的代码实现之。
/ A( u7 M! z, b( e( u  第三步,逐步找到其他需要修改的地方,比如用于得到字符串宽度、高度,指定宽度的字符串换行显示等函数。+ R* D9 T, M3 C: a8 g
  7 k9 Q  }8 Z/ @# T
  & _$ ?! o( L, H$ S
  【具体实现】
( P4 w& G  L. `7 N& }+ `* P  我用的是注入dll,然后打内存补丁的方式。这样的好处是便于更新,可以任意修改实现过程,以后游戏出了新版本,也只要修改几个地址变量,重新编译一下就可以了。
9 c6 M& W+ b% [, `' W  另外一个好处是,不以文件补丁的形式发布,没有版权问题。(有人关心这个吗?)2 d3 ]) P6 K1 v3 L- o, S, f  I
  8 [  |: O6 c- E8 M/ f2 F
  源码在这里:0 A- `1 T" B3 `+ t3 V3 g
  http://gsbzhcn.googlecode.com/svn/trunk/src
% N! G" B' i& ]  G5 |& j  
: t5 i. C! R1 G$ n2 f, B4 V3 w  简单的介绍一下流程:
2 \8 i( \4 p2 t  1.CreateProcess启动游戏的exe,并使之处于挂起状态。
1 q9 ^2 p( }, Q; @/ n8 p. ?  2.VirtualAllocEx在游戏进程上申请一块内存,WriteProcessMemory往里写入要注入的dll名称。6 }5 |$ {: h- R. _8 z5 W  x2 d
  3.GetProcAddress得到LoadLibraryA的地址。) z+ t4 c% p' E+ \$ Q/ B. s5 k
  4.CreateRemoteThread运行LoadLibraryA,注入dll,dll载入时会为游戏进程打上补丁。
$ J" l2 X  I: ^' R1 I6 Z  6.WaitForSingleObject等候dll载入完成。
3 G) n( b+ ?( b  7.VirtualFreeEx清理掉之前申请的内存。. R6 @6 W/ ?& \% p8 l9 D5 }
  8.ResumeThread让打过补丁的游戏进程运行起来。
; W6 @3 v: o  G, H1 ]* b; G+ [2 U  
0 U, ~0 O+ V* [, _2 Y  内存补丁主要是让游戏在关键的地方跳转到我们的dll,执行一段代码后再跳回去,或者直接用dll里的函数代替之。
: r* `7 p2 H. u- l  
! H7 k7 y0 ]1 s& I& F  ( J. B  L" r! v
  【结尾】
; w# ~7 B$ Q, n& _! q5 k8 }  此游戏的汉化正在http://code.google.com/p/gsbzhcn/ 进行,文本不多,奈何翻译人手也不多,希望有兴趣的同学能够参与。
! \: E  o; L& `- N7 ^/ j! \& \! X  
2 C( {7 ~, v7 F: U* n--------------------------------------------------------------------------------) m9 f  I: i! {) n4 Z
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
4 `# o1 ^2 `; ?5 S6 u- V- ^
6 R$ b& R6 p6 F3 s4 ~' W                                                       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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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