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

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

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

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

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

【转】DirectX 9 游戏汉化详解

本帖最后由 shane007 于 2011-1-30 14:13 编辑 4 s% ?: |6 `" N& r
) f; Q  R/ @; ~+ g: `
作 者: noword_forever, @7 a' ?6 C6 v# e4 h/ f3 t3 I
时 间: 2010-05-25,14:52:51
8 l) D) S1 `: v( W. [+ Q  O( x链 接: http://bbs.pediy.com/showthread.php?t=113739
# H. j1 j3 P* Y! C8 _; N% q4 v
: `) x! U0 X) I【文章标题】: DirectX 9 游戏汉化详解  [" l) h' f( N+ K" h- q- f
【文章作者】: noword, ?8 `# K, C7 u! J/ x
【软件名称】: 无厘头太空战役/ H& g; ?4 f6 ^& X. D7 q! g
【下载地址】: http://www.verycd.com/topics/2819995/
- @8 P$ @0 V9 p; R$ I--------------------------------------------------------------------------------
, p$ M, s! X* ^8 Q$ h  【前言】
( ?% Z+ q: l3 {+ _% Q  先copy一段此游戏介绍:+ S4 [) X9 j4 C# D/ j
  1 y4 A. Z4 D. K, L8 ^& ?2 }% b
  这是一个独特的战略游戏,具有即时战略与塔防的混合风格,玩家将扮演庞大太空舰队的最高指挥官,你可以自定飞船的构造,摆放飞船的位置,下达命令,然后观看绚丽的射击与爆炸。移动和爆炸时会有动态模糊效果。支持自定义地图。
% K  R0 \* J$ U- |4 k* p7 u  
& m6 H7 x0 c* z5 y) q1 y4 E  想玩中文版,两个游戏论坛,3DM和YX上,都有人说要汉化,等了几个月,没有下文,说是技术原因。于是决定自己来试试看。* N& V6 g( ]8 I* l. ~3 x9 A
  4 n" o  ~) e  Q6 z
  
* u  ]3 `9 [7 n9 V/ A3 l  【困难何在】$ z0 C) z! `: G/ U7 R
  此游戏的文本都在data目录下,都是明文的文本文件。修改data\strings.ini,将( j9 _  ]) W, B  a& k
  
. D# X) ], B( T  j# C. H+ [. H代码:
7 h/ r$ s2 q% J1 x( ~/ z$ G  MAINMENU_QUIT        = "Exit"3 |4 T/ z, g/ @- B7 V
  
9 w5 k2 e* S9 X$ Q2 p9 v  改成; U+ F9 V2 w7 d! @1 Q0 w; }
  2 E3 x1 d; X7 X* t: C' U! E- g
代码:
& n& o9 Y  P( z* \9 A  MAINMENU_QUIT        = "退出") ?& \4 J' o* w( ?) V
  9 [3 s/ [' M  H, j* s
  
7 v! I% ~6 w( p9 ~2 \  进入游戏后,不出所料,无法显示此中文。% a( G! T9 u1 L/ V
  
8 Z. T, M* f7 T6 c. ?1 J' c  茫茫多的游戏爱好者,在尝试汉化某款自己心仪的游戏时,都是死在了这一步——找了半天文本资源,然后翻成中文,满心欢喜和期待的进入游戏,面对的却是一堆乱码或一片空白。满腔热情,化为乌有,无可奈何,黯然神伤。% U4 e: s$ Q9 I, f
  
4 [5 g, b8 D- V$ k  本文的目的,就是希望能够帮助这些有志于游戏汉化的同学,主要介绍了如何让一个英文的游戏,能够正确的显示出中文。. U+ H) a. X7 i
  
+ j7 t  b9 s2 m! U8 N  ) ~6 R" F: U4 I
  【调试分析】
$ S8 Q: A# _# e) M+ W) ]8 E  DirectX 9游戏的启动流程是这样的,先执行Direct3DCreate9,返回值是一个IDirect3D9句柄,然后执行IDirect3D9->CreateDevice,得到IDirect3DDevice9句柄。5 o) S+ u( D: O0 R) i) [: F% R7 c
  有了IDirect3DDevice9就能使用DirectX 9的一切绘图手段,而我们最关心的就是能够使用D3DXCreateFont来创建ID3DXFont,继而能够非常方便快捷的在游戏中显示文字。
: ?: C! C# q/ K9 ?  % O& ^; r5 a0 [! p
  用ODBG载入游戏的exe文件,“查找所有模块间的调用”,找“d3d9.Direct3DCreate9”:
! o( t: U6 q+ @  
! m8 C8 g: D7 C1 ]' t, p! y代码:
" ?3 r; M5 s8 I- S' Y: f  00501974   .  BB 500A5400        mov     ebx, 00540A50                   ;  ASCII "Initialising 3D Engine"
6 K; g9 W" U: J5 l. w3 ~  00501979   .  E8 22130000        call    00502CA0
, l  D* H, ?/ f5 p3 z  0050197E   .  6A 20              push    201 o, p8 Q8 B7 @4 j  h
  00501980   .  8977 18            mov     dword ptr [edi+18], esi
; e  p$ t& [$ k, I& ?& F  00501983   .  E8 2E8B0100        call    <jmp.&d3d9.Direct3DCreate9>, d6 z% Y; d, Y6 l& D, Y
  00501988   .  85C0               test    eax, eax
8 Z: u: M! k6 D5 k. H5 J  0050198A   .  8947 10            mov     dword ptr [edi+10], eax         ;  edi+10 = 58d550
9 O: [+ v+ p# ^+ G/ O  & `$ B5 }# L0 Z9 @1 A) R# j
  往下找,就能找到IDirect3D9->CreateDevice:
; e' D/ I$ Y1 q8 c2 T9 ]  * n- s4 E6 A+ o8 D
代码:5 q6 Z, T4 t; T! x7 ^2 ^
  00501B4C   .  8D77 14            lea     esi, dword ptr [edi+14]
- p( \7 w' ]) v3 \* q  00501B4F   .  56                 push    esi                              ;  58d554  => IDirect3DDevice9; U7 r; w" x+ [4 O: g) H, f
  00501B50   .  8D4F 40            lea     ecx, dword ptr [edi+40]8 j+ x- _, L; i9 w  ^
  00501B53   .  51                 push    ecx
) f# l$ U3 ?' J" |3 ~& n) z  00501B54   .  6A 40              push    401 G) n9 J' o, t( r7 y: Y3 [
  00501B56   .  EB 14              jmp     short 00501B6C* H* e! r! K9 x. N7 \1 U+ N$ R
  ...
& H8 F- l1 Y9 l6 d4 X' S  00501B6C   >  8B4F 18            mov     ecx, dword ptr [edi+18]
3 d% n$ z* g$ o% E! l  00501B6F   .  8B47 10            mov     eax, dword ptr [edi+10]' M' c3 j! B8 X6 U" v
  00501B72   .  8B10               mov     edx, dword ptr [eax]! ~1 M2 m; ?" T! C% d1 A
  00501B74   .  8B52 40            mov     edx, dword ptr [edx+40]
8 n% z, [+ `* G  00501B77   .  51                 push    ecx
# i) s+ i  l# }4 H  A& E  00501B78   .  8B4C24 24          mov     ecx, dword ptr [esp+24]
8 A& V% n5 S# V$ X5 @  00501B7C   .  51                 push    ecx
/ V6 a& X0 a- k, U/ V! q; @/ |+ b  00501B7D   .  55                 push    ebp8 l! \! v/ W* N$ `
  00501B7E   .  50                 push    eax
' e' `9 |) {: j5 w  U2 j  00501B7F   .  FFD2               call    edx                             ;  IDirect3D9::CreateDevice
/ w# Q8 b& O2 s  
' U7 D. C" Z. G9 |8 R) Y  2 o0 k* u2 Z0 _! n( o% \' G; ~
  由于是所谓的COM接口,没有十分明显的标志,不是很好找。
7 L* Y! U3 j) ^  % Q, k' M6 x7 o3 k8 X2 w& F
  在微软的DirectX SDK d3d9.h文件中,IDirect3D9的接口是这样的:
; k) h1 j5 H9 c9 w% z; ?% M3 L  
5 J5 X" w8 E$ v; M. b  
4 U3 K8 ?/ Q, `$ r代码:
) F) T3 d# N/ Q4 I4 V4 O  DECLARE_INTERFACE_(IDirect3D9, IUnknown)
8 y/ C7 }# P1 H: E  {
5 Y1 _+ s$ ?- F9 j      /*** IUnknown methods ***/
- h- I$ ?% z: z      STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;3 G9 K0 T$ o+ L7 y% Y
      STDMETHOD_(ULONG,AddRef)(THIS) PURE;$ Z! ]8 k* h7 M4 b) e2 P1 f
      STDMETHOD_(ULONG,Release)(THIS) PURE;% s8 U5 ]5 m, n' B, H+ u. I
  
- p! O0 f% E0 r5 b3 ?      /*** IDirect3D9 methods ***/$ s" h1 B" ]" v" `/ l$ i3 u! `
      STDMETHOD(RegisterSoftwareDevice)(THIS_ void* pInitializeFunction) PURE;
  Z3 {* I1 q3 K5 p      STDMETHOD_(UINT, GetAdapterCount)(THIS) PURE;  s7 y+ d5 B; \  a3 Q0 z
      STDMETHOD(GetAdapterIdentifier)(THIS_ UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier) PURE;1 a) q6 r9 u+ {" |) D
      STDMETHOD_(UINT, GetAdapterModeCount)(THIS_ UINT Adapter,D3DFORMAT Format) PURE;- S/ O4 x8 n3 u- x- r
      STDMETHOD(EnumAdapterModes)(THIS_ UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode) PURE;
& S! F. W/ E3 u. @1 P      STDMETHOD(GetAdapterDisplayMode)(THIS_ UINT Adapter,D3DDISPLAYMODE* pMode) PURE;
% N- R. j; k, [# S      STDMETHOD(CheckDeviceType)(THIS_ UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed) PURE;4 ?, ^! t8 w) O
      STDMETHOD(CheckDeviceFormat)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat) PURE;
( o, N  O5 ?+ L      STDMETHOD(CheckDeviceMultiSampleType)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels) PURE;
- B1 r! [2 A4 ]      STDMETHOD(CheckDepthStencilMatch)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat) PURE;6 M" ]& `! R# I) h
      STDMETHOD(CheckDeviceFormatConversion)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat) PURE;
" U0 o" t! {  H3 M) O; {3 [      STDMETHOD(GetDeviceCaps)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps) PURE;
# q% ^7 c) H) h, g      STDMETHOD_(HMONITOR, GetAdapterMonitor)(THIS_ UINT Adapter) PURE;9 [0 L9 `  I: r  K3 {
      STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface) PURE;
7 K# Z% M% I  M1 `+ N      * ^3 r# @9 i! p. B+ `( C4 b6 x+ s
      #ifdef D3D_DEBUG_INFO
- f4 C$ H! g- C      LPCWSTR Version;
7 B3 v" c% t! S9 r* l      #endif0 W) v' O1 i* r
  };
4 P8 A# j4 y2 N1 j! ~6 {+ x: M  9 {4 I* ?# [3 @, R7 a5 i" T3 q
  0 n5 a4 s5 X2 D) ~9 D
  CreateDevice是第17个函数,所以它的地址是(17-1)*4 = 0x40,1 H4 C, r$ ?3 W# S
  00501B74   .  8B52 40            mov     edx, dword ptr [edx+40]9 y+ O9 d2 p# J" e2 e
  这里的edx+40就是这么来的。9 v1 }; x2 Q$ [  ]* t
  5 T0 [2 B+ _0 s& B) w" Y
  如果觉得算起来很麻烦的话,还有一个简单的方法,可以自己编译一个d3d9的程序,然后反汇编看看。
7 w$ I3 S# X( l- ]6 D- Z1 S  
/ d0 i6 Z: T. g  如果还觉得麻烦,还有个更简单的方法,直接往下找,通常会有一些调试文本能够帮助定位,例如:
8 H& l& {: u4 i7 g  00501B86   .  BB 600B5400        mov     ebx, 00540B60                   ;  ASCII "CreateDevice"
9 s7 O: _4 O  o$ t5 \  ...) t8 v( l  m4 R0 K$ O
  00501BBB   .  BB 700B5400        mov     ebx, 00540B70                   ;  ASCII "CreateDevice failed again"* d2 J0 O% n, |; N& m3 w. p( X
  当然,这个办法并不通用,有效与否完全要看游戏作者的脸色。
4 O8 t4 p/ f% e9 A5 z8 @/ @) Q  
3 x# x& i& k- Z  j7 s  e  知道了IDirect3DDevice9的地址,就能植入我们自己的初始化ID3DXFont的代码。9 [* p/ C  J7 c9 L4 c3 ~4 S5 Y, ^' D
  
* g6 k# `7 a/ b1 |: M  有了ID3DXFont,下面就是要找到用于显示文字的函数,并用我们自己的代码来替换实现。( r* {6 k- I# {2 b6 P6 r$ ]4 B
  
# `% R. C* n5 a: X! [  随便找一段游戏中出现的文字,比如开始菜单上出现的“Full 1.37”,ALT-M,进入内存窗口,在所有搜到的该字符串上下“内存访问”断点,最终会找到地址在4FFF50的一个函数。1 c, j7 Q6 B4 N2 ?4 C- _* H- P
  1 K# s: m9 m1 Y, g& c( z& U
  该函数返回时,用的是“retn 14”,在4FFF50处用“retn 14”改写,切回到游戏后没有任何字符出现,说明这个函数正是用来显示字符的。
5 j# f" f7 Q7 N8 w9 |% Q: j  % r) C5 T4 f) O' E; F4 f. C& T7 f, A
  原谅我在这里对于怎么找到4FFF50的过程含糊其辞,一笔带过了。确实没有什么取巧的方法,完全取决于破解的功力,良好的耐力,以及一点点好运气。而这也正是游戏汉化的难点所在。
5 q: [/ P. V6 ?6 O$ |  
) D% m' W8 q# w# B  找到字符串显示的函数后,还要弄清楚该函数的接口。' ?- ^' {& V9 }' H! J
  4 r7 r* v! ~% E3 m  b6 e% U
  在屏幕上显示一个字符串,通常需要知道这些要素:字符串、显示的位置(X,Y坐标)、颜色、字符的大小,以及一些flag用于表示左对齐,右对齐,居中,加粗,倾斜等。
( M3 v' N- T% K  
/ k9 T  i8 r. V3 b8 l  前面说过,返回用的是“retn 14”,说明栈里有20(10进制的14h)/4=5个参数,当进入该函数时,栈上的数据是这样的:
, t8 k  y. }& B9 c' Q. r  
. m2 B7 B" @) W. f: v0 V- R1 Y代码:
8 F% ]& I% O4 b. q" E' [6 O$ ]  0012FE84   00453C48  返回到 GSB_1_37.00453C48 来自 GSB_1_37.004FFF50
  q8 z2 x4 \+ U1 K  0012FE88   0012FEB8  ASCII "Full 1.37"
* K# b& p/ \; `5 V0 @# o9 v$ Y) R  0012FE8C   00000000- L& ^) [, S. ^  s- O" L% G* i
  0012FE90   40400000- s+ T* }$ C, ^/ a9 b
  0012FE94   FFFFFFFF; x; `! j' Y) @
  0012FE98   447D8000
1 P+ j; G3 W3 u1 j2 p  
0 k* }- y, ?! C1 D# B6 h  第一个,很明显就是要显示的字符串,后面几个是什么玩意儿呢?
/ a2 w9 C8 x3 D9 R/ ~3 a& u    ~/ P; H8 ~$ w- x, Z
  回到调用004FFF50的地方,在00453C1D下断点:
5 a; `# k' }/ y+ E1 G- P  : W, S( V, L5 Z
代码:- v( ~$ q6 s2 o, g
  00453C1D  |> \D94424 14          fld     dword ptr [esp+14]
, V* M$ E6 m7 m. B+ @1 a4 A, U  00453C21  |.  51                 push    ecx
) S' I' _8 a6 H6 B  R* _  00453C22  |.  D91C24             fstp    dword ptr [esp]                  ;  参数5  1024.0; P7 [& [8 T* |$ w. d  I: j
  00453C25  |.  6A FF              push    -1                               ;  参数4! w0 c! f# o) X9 j
  00453C27  |.  D905 F4125400      fld     dword ptr [5412F4]; x& u+ n- \( R: u1 E: P. M
  00453C2D  |.  83EC 08            sub     esp, 8
3 [4 J( v% q. n9 C4 t  00453C30  |.  D95C24 04          fstp    dword ptr [esp+4]                ;  参数3  3.02 \1 S% B: e/ i$ L  z* H
  00453C34  |.  8BD0               mov     edx, eax
& [8 ?- o* m" f) k# t  00453C36  |.  D9EE               fldz4 L& n) C4 [  M  R5 G6 b: S" h
  00453C38  |.  D91C24             fstp    dword ptr [esp]                  ;  参数2  0.0/ v9 t+ U  h* c+ B
  00453C3B  |.  56                 push    esi                              ;  参数1
& Z5 X  B7 O7 t/ `! G) s/ R+ z# H  00453C3C  |.  BE 01000000        mov     esi, 1$ i; e0 b8 S0 I3 N" I
  00453C41  |.  8BCE               mov     ecx, esi
) c6 i% E& a$ g$ l: ?  00453C43  |.  E8 08C30A00        call    004FFF50( }) U$ q' S8 Y6 A+ Q9 f& v" D
  1 k3 \) F  J4 j9 U" v
  
4 @3 I! V  y3 @% S  可以看到,参数4是一个固定值,第二、三、五参数都是浮点数。# Z$ a! w4 D& `/ E2 y
  ) A5 ]. H7 Y- }5 a7 h3 \: D& w
  这里有一个技巧,在函数开始的地方修改参数的值,看看会发生什么变化,很快就能知道参数的作用。/ }5 ?. F7 O( J4 j" f
  ) T* L  e7 t+ c, n5 Y9 x( [; G
  参数4是颜色值,Alpha和RGB值都是FF,就是白色,与在游戏中看到的字符颜色相同。
, {% |" M3 E3 K3 u  参数2是X坐标,参数3是Y坐标,参数5用于调整。8 f7 d6 ]( M9 m7 {) d! m/ N
  需要注意的是,还有两个参数是通过寄存器ECX和EDX传递的,ECX用于表示左对齐(0),右对齐(1)和居中(2),EDX是固定值58D6D0,一个全局的结构或类。; a9 q, Q7 \/ v2 l8 G
  
; g" G5 c0 m+ z6 }, i5 e$ f  此游戏有两种字体,因此用于显示字符的几大要素,现在还缺一个,就是不知道如何判断字符的大小。+ `  W* K1 b2 w
  
1 s* s8 i2 p! j3 m7 n' p  在用于显示文字的004FFF50的上下断点,多跟几次,就会发现,每次调用以前,都会调用一个call:
7 U; ^' f& x( W% q  , z  ?" h) {% G' @. Y/ m' m( _9 E
代码:6 d, h5 x4 v, V* F, Q3 P$ a
  00453BD5  |.  BE 44035300        mov     esi, 00530344                    ;  ASCII "zekton16.dds"% I; x8 v( a% Z+ x- `
  00453BDA  |.  E8 91B50A00        call    004FF170+ c# r# g3 Y" R; P1 p. F
  - ?' x- b, ?% a) o% L
  004479E7  |.  BE 54035300        mov     esi, 00530354                    ;  ASCII "cwfont20.dds"
5 j+ T  A: D+ a( _' d+ b; Q3 T  004479EC  |.  E8 7F770B00        call    004FF170
& j5 A5 [. D: I8 Q9 @  , P+ e# @" Q0 s
  在游戏目录data\font下面有两个文件zekton16.dds.dat和cwfont20.dds.dat,由此判断004FF170应该是用于选择字体的函数。
1 I- z) b. i/ J# J/ O  
/ O& ]) \- ~" u  [  总结一下:* J& v# G; w5 }7 ]5 N. X- C/ U& `0 L
  第一步,找到IDirect3DDevice9句柄,用于初始化ID3DXFont。, f6 n. q4 K. C
  第二步,找到显示文字的函数,用自己的代码实现之。
' J% {! q: F# ?  第三步,逐步找到其他需要修改的地方,比如用于得到字符串宽度、高度,指定宽度的字符串换行显示等函数。
3 M9 d- `: V2 W& y, \  0 k' S* [+ G* h$ B, v
  % Z( N9 W5 w$ o" u; v9 g% {% p
  【具体实现】6 K" x: Z8 V& E, f
  我用的是注入dll,然后打内存补丁的方式。这样的好处是便于更新,可以任意修改实现过程,以后游戏出了新版本,也只要修改几个地址变量,重新编译一下就可以了。( g+ A5 R$ ?# E, j5 ?
  另外一个好处是,不以文件补丁的形式发布,没有版权问题。(有人关心这个吗?)
: o4 Y  ]8 Q( ?3 T4 l% r2 _- `  
! G) c, Y' o: X  V% g$ B% G" z  源码在这里:, G7 i, F: O% I
  http://gsbzhcn.googlecode.com/svn/trunk/src. h4 o$ E4 Y% x! e
  & i$ K; D& T0 r$ b' h
  简单的介绍一下流程:* v7 }9 e/ l7 b/ D1 E- f2 S1 {3 C
  1.CreateProcess启动游戏的exe,并使之处于挂起状态。
+ ~- M0 n- ?& O$ o- V! U  2.VirtualAllocEx在游戏进程上申请一块内存,WriteProcessMemory往里写入要注入的dll名称。
8 S6 b! _  F- x  3.GetProcAddress得到LoadLibraryA的地址。9 M) b4 M' }2 @1 g; t" v
  4.CreateRemoteThread运行LoadLibraryA,注入dll,dll载入时会为游戏进程打上补丁。
" k2 N( J, O. k* v6 e& j- D  6.WaitForSingleObject等候dll载入完成。
1 w* z9 j+ a% g# Q$ V  7.VirtualFreeEx清理掉之前申请的内存。2 e; w( o: V# t) M6 f
  8.ResumeThread让打过补丁的游戏进程运行起来。
$ N+ ~7 Z. W" L* c0 a  
  v  S. v5 {% r" D" }  内存补丁主要是让游戏在关键的地方跳转到我们的dll,执行一段代码后再跳回去,或者直接用dll里的函数代替之。
. V1 g/ M+ N: U6 A2 g  & I! I! z+ z6 m7 L  v
  4 ]; X0 E, Z7 k+ C. z0 D; _* V8 d) P
  【结尾】0 u* M  a9 F3 i, k
  此游戏的汉化正在http://code.google.com/p/gsbzhcn/ 进行,文本不多,奈何翻译人手也不多,希望有兴趣的同学能够参与。
' `4 k! c7 ^2 P: |; ?  
5 y8 b# o! Y/ s0 u/ Y--------------------------------------------------------------------------------
: [+ z7 a" n- n' y【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
- X- j9 b3 [/ m1 y( a, M8 \6 j  h  G0 i1 ^: |: \" o: o' a7 @) n
                                                       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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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