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

建议 【Opengl游戏汉化 #5】 尼比鲁:秘密年代 (NiBiRu)字幕显示函数

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

[建议] 【Opengl游戏汉化 #5】 尼比鲁:秘密年代 (NiBiRu)字幕显示函数

跳转到指定楼层
楼主
发表于 2023-8-27 13:49 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

【Opengl游戏汉化 #5】 尼比鲁:秘密年代 (NiBiRu)字幕显示函数

本帖最后由 shane007 于 2023-9-5 16:49 编辑
, S8 j) c! K' s1 [2 k( G* x3 q% X
9 l+ \) @& b, ~) X0 J+ ^这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎+ W; l/ [- t" K' V
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。& ?) k2 r* ^2 w+ G9 {
https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081  _5 ~3 S$ r6 W. w5 Y0 a! k
第1处$ u; c2 K; k1 S; ?
  1. void sub_451474(char *a1, ...)
    . V3 y! z2 K- u, y
  2. {
      H4 L7 e- p# U; D$ u$ t9 u
  3.   GLsizei v1; // eax* J; }4 b" Z- o* J+ |& P
  4.   char lists; // [esp+4h] [ebp-800h]6 V3 Z" I) g& f  I# x
  5.   va_list va; // [esp+810h] [ebp+Ch]1 ^; l. A( e* N1 z7 R$ s

  6.   h, c6 Z2 a# t4 O% l' H, j  R
  7.   va_start(va, a1);9 d* X1 h# l7 G) R
  8.   if ( a1 )" D4 l2 }, {6 V# v5 R
  9.   {
    ! C" |, g# R. C) y( L* M  H; |
  10.     vsprintf(&lists, a1, va);
    2 K; i: O1 w% b& n
  11.     glPushAttrib(0x20000u);
    - e2 k2 ]( q$ T' [4 N" Q5 H: Z
  12.     glListBase(base);
    7 Z/ [- @4 ?6 a8 e3 g2 w; ~
  13.     v1 = strlen(&lists);8 N2 [$ z4 J4 q! ]8 x4 ?& k
  14.     glCallLists(v1, 0x1401u, &lists);. H6 x7 d- m9 ]8 H2 j: ]
  15.     glPopAttrib();8 p# C% u+ t" }4 ?/ T# Q
  16.   }
    ' t  o  N  u8 m
  17. }
复制代码
* }8 C8 J$ G! p2 f
+ p+ l, _3 W( F/ f

) z$ @' k0 |3 d1 \( n( Q6 N" ~第2处; b0 d  @: A! O7 G' F; g& [
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    ( O% G, |* S7 |2 p, m/ J6 e1 L
  2. {: ]+ I: g% o7 t
  3.   int v4; // eax" n0 {/ e, c; D0 p, v4 E7 o; V
  4.   GLsizei v5; // eax/ b" j" F& x8 y; M+ B
  5.   char lists; // [esp+4h] [ebp-800h]
    0 U$ x( e; Z/ E+ e' U; {
  6.   va_list va; // [esp+81Ch] [ebp+18h]6 H4 s# s& \. F; b; \2 }
  7. # O" `3 r( g+ H0 M9 s
  8.   va_start(va, a4);
    + F# _6 D  e: b# `( L: C! _# X
  9.   if ( a4 )# k) f. z' ^, }. n- k1 J; M
  10.   {# `* i% O# y+ |2 P( ^+ U: U* X
  11.     sub_44F8A0(a3);" ?: |- W* s+ |/ R, u
  12.     v4 = sub_40BB44();' a) X. L. r- j1 V1 z
  13.     glRasterPos2i(x, v4 - a2);
    7 B# a# R. y% e3 D% U( w* l
  14.     vsprintf(&lists, a4, va);
    5 t1 W4 K3 Z% G4 P
  15.     glPushAttrib(0x20000u);4 p" k7 Q9 O- W* V7 g! j9 _' Q
  16.     glListBase(base);
    ! I, J" C4 f% v1 F7 ^4 G9 h6 d' g) Q; i9 I
  17.     v5 = strlen(&lists);
      y+ p5 j; N2 o, j9 y3 S& x% x5 D0 E
  18.     glCallLists(v5, 0x1401u, &lists);
    $ k% ]$ [" e7 I7 j5 u) ]
  19.     glPopAttrib();
    * E: m5 Q" P9 t. }1 H
  20.   }
    ! K0 p8 c% w. L- ?2 C
  21. }
复制代码
2 P( z# h5 M1 m  ]. r

: Q/ ~# {( X& W4 S2 b2 s# Z, O/ V4 [% W  `, X, ^
第3处1 V; N; b- i/ ?5 z" M

  1. 8 t( e; @4 ~9 b- \$ _0 |7 K
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)3 B9 D% \1 D, T, V0 P5 j
  3. {
    + X' M$ N# V) R' e. l2 Q# q3 E/ t5 N
  4.   GLvoid *v7; // ST08_4
    % s1 U/ i# o6 A! o
  5.   GLsizei v8; // eax2 J- F4 d; m8 w1 C5 V: W
  6.   int v9; // [esp+0h] [ebp-1018h]
    4 x7 p( [0 p4 ]1 O- p6 H: }7 g2 |
  7.   char v10; // [esp+8h] [ebp-1010h]
    1 F  W' V; i+ |: [. K2 h( w
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]3 O/ @; A1 B- K$ r( _9 N0 l
  9.   char v12[5]; // [esp+1013h] [ebp-5h]& L# L7 X* z& }! N. ~
  10.   va_list va; // [esp+103Ch] [ebp+24h]
    5 ^9 Z1 {9 [* k& |1 i# C
  11. ( a( l# q! y& g5 c. y
  12.   va_start(va, a7);
    # K, X  a$ F5 V
  13.   v9 = 1;
    ! D( I7 f# E; Q) @" |4 X
  14.   if ( a7 )
    # ?# o5 |+ j8 C/ x" K1 A
  15.   {
    1 q" |5 K3 y% Z: Z" u+ t
  16.     vsprintf(&v10, a7, va);9 x9 N. d4 [- w+ k
  17.     glPushAttrib(0x20000u);/ G* i2 M( x* h- p% @* l" x
  18.     glListBase(base);
    6 ]! @) J. r2 G' Y3 r: k
  19.     lists = &v10;) t# X( l" C. N' ]9 G
  20.     do
    8 F$ p) j: }6 \# l
  21.     {$ W2 R, f6 N7 O0 s; V, f
  22.       *(_DWORD *)&v12[1] = lists;
    1 u: P$ C8 L; [, |1 x2 ]" b
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )
    & L4 ]2 m0 t* n, X2 x; I/ @) ?0 Q
  24.         ++*(_DWORD *)&v12[1];
    0 b8 B* p) K0 r' v+ Y8 G+ F
  25.       v12[0] = **(_BYTE **)&v12[1];' e% W& s# A0 c2 T) C* P
  26.       **(_BYTE **)&v12[1] = 0;
    ) [: G$ Y4 z) D' m4 U0 I' j
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )  B/ n1 O: w9 ^' x3 ?
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    , c3 B0 e/ Q$ L/ Y
  29.       y -= a5;
    / V+ o8 n) m9 t: L
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    0 j' y, P% ]9 r5 `* p1 L! u" D
  31.       v7 = lists;
    7 Y# G3 P$ w& l2 c! r2 j% _: f+ {) c
  32.       v8 = strlen((const char *)lists);
    4 x" [$ A' j+ Y3 L' V% M' ]$ r
  33.       glCallLists(v8, 0x1401u, v7);7 o& I/ i4 D7 ?# ?
  34.       if ( v9 < a3 )
    6 A, r, L# k/ f/ k+ \: C9 E
  35.         a4 += 4;
    6 s6 ?- L6 `: ~
  36.       ++v9;
    5 Y' r. U" j, O/ ~; Z, |: v
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);- ~, y7 o/ C+ v" A  l& e5 C
  38.     }
    ! Y3 D. P: h2 I; I
  39.     while ( v12[0] );
    + K) G$ y* c- c: i7 q  |8 @/ A
  40.     glPopAttrib();
    ) S6 g* q+ B' e6 @* b' @
  41.   }* v' I- y( j' I; g
  42. }
    2 @. G9 h+ Y) e
复制代码
* N) W! I2 C  P# W. M
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
6 z+ f5 s' k! M  D9 `* k) Z; E6 B- A0 g7 p
  1. .text:004512B1 52                                         push    edx             ; char *( J% p/ F) J$ r: _
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]" H( m9 A8 m2 [5 h1 M8 Z
  3. .text:004512B5 50                                         push    eax             ; base
      D3 M* F) y" ~, ^7 u
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    ' e, R( j) D) M. V- X. B7 x3 `
  5. .text:004512B9 51                                         push    ecx             ; int5 e: \9 S$ Z8 a9 ~4 @, @
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]
    $ ~: `# `+ Z3 @
  7. .text:004512BD 52                                         push    edx             ; int
    4 Z% x  u2 t; v, a3 b
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    + H. P' t3 P& v3 J; q+ `
  9. .text:004512C1 50                                         push    eax             ; int
    ; Z8 T- k9 v( e5 A! T: E9 F4 ~
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]- B0 h( l" R& V# W& e1 e- G1 b! N
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    * P7 \# C. X, {! C+ b
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    ) N  u+ b' p- Y' M. J4 k6 l5 R* u
  13. .text:004512CB 51                                         push    ecx             ; y
    5 X( N! E& L3 T( x3 L5 S: `! J3 `
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    ! b8 M4 }% E2 P& {8 n3 T& i
  15. .text:004512CF 52                                         push    edx             ; int& ^7 j6 m, ^" j2 J) Y$ n4 V+ A7 X
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
. O9 L+ X; V0 [- s4 {0 n
chatGPT整理过之后,如下
& O8 A6 S0 E$ y  n
3 ]4 X( R0 k' ?$ d
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)( d, G: m) e4 G6 L
  2. {& D6 V( g' i2 T4 k1 i  `% ?
  3.   GLvoid *textData;         // 存储字符数据的指针/ T& Q' W* l6 w2 s
  4.   GLsizei textLength;       // 字符数据的长度. v2 m4 S1 e2 N2 O& s
  5.   int lineIndex;            // 行索引0 g. D3 d, R2 X3 Y9 O/ ^2 J
  6.   char formattedText[5];    // 存储格式化后的字符数据8 q! U2 D% O9 Q
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    ' C( d8 }9 p& L) l5 t3 e! g
  8.   char buffer[5];           // 字符数据缓冲区
    0 d8 C% t8 V; l# Q. E+ L& e
  9.   va_list args;             // 变长参数列表$ [- I: q/ \: |
  10. & l) F: d9 V5 S
  11.   va_start(args, text);     // 初始化变长参数列表
    1 o. N' E. v% T! C' U! l
  12.   lineIndex = 1;            // 初始化行索引为1
    $ g' s' X- V* n- @+ R

  13. 6 }6 L% d4 B4 k, e. s  q
  14.   if (text)                 // 如果文本不为空: v6 j) o2 J5 w: Z+ Q/ g
  15.   {
    0 [: H- Y  U* Z2 U- u
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中9 z6 @4 ~  ~7 D; K+ n4 X
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
      }$ `  H) A( L9 S2 v6 l6 X$ O
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    : b2 p- A) i" @
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置* \3 J' i$ G) q

  20. . K+ m# y; S0 x  w: {* r
  21.     do
      i# j9 d6 z$ Y/ G5 @( s
  22.     {
    4 U  D$ A3 u6 C) ~7 f" B( W2 K: w" o
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素5 ?! |$ e: P, A2 c5 Q

  24. 7 B' Z' x& o1 ~( r5 y
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束  x: J. |% `/ R! x, h& u
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素9 w6 W- W0 H/ V" `* {! B, _, e

  27.   ?1 h! D0 b% X/ B: O4 X% b
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    9 Y0 u4 f8 W9 G  t
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符
    5 s  O; Q% Q7 U( B

  30. 5 t& o  T3 J% A
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)" G* T" y5 r8 @$ j0 i
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符4 R8 N' I. }3 F
  33. ! t! V% @! A7 R0 e+ P- D# Z% [
  34.       yOffset -= lineHeight;                // 更新y坐标
    8 d* h! `# h& F* f+ L5 K
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置/ R4 N) |! [/ p2 L
  36.       textData = currentLine;              // 将textData指向currentLine# W+ [) Z( H, d% t
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度9 A; q/ x& x2 g
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表8 [: \5 p, o" ~1 X) i* ], Z

  39. / f! ]# w! x: G! t% O5 T
  40.       if (lineIndex < numLines)
    ! _8 u3 y) U2 e3 p& L- Z
  41.         lineOffset += 4;                   // 更新lineOffset. q4 Y2 u7 l, I
  42.       ++lineIndex;                         // 递增行索引
    & P" h! [7 R% h: @
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    , V* G7 ?5 G6 [. I
  44.     }9 k$ r1 V! h0 `/ v9 b; t
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    # E3 S1 G' a7 \4 t/ |% \# [
  46.     glPopAttrib();                          // 恢复OpenGL属性状态4 c; R; p. b! k! j0 a
  47.   }1 Y. l% K  W: H3 g, H/ z
  48. }
    ' V" ^' A8 H7 u7 c" i
复制代码
/ b. K; q/ J% B
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
% \# I# d( Y8 }2 |; r( u6 a2 t8 C# N( R3 g/ S7 i0 j
int xOffset,      字幕的x坐标# y+ l- Z! d) c( ^
GLint yOffset,    字幕的y坐标
$ j5 o8 l* J( ?) Iint numLines,     字幕的行数(较长的字幕为2,一般为1)* x% l1 T& V8 S' h/ }+ T, Z
int lineOffset,   这个需要再研究1 {; ?5 O1 e5 z4 a  n
int lineHeight,   字体高度(或行高)! Q/ a4 A+ U, W/ T# V* w
GLuint displayListBase, 这个字体对应的base值' F6 W/ S! k3 }+ `" E
char *text, ...         字符串
+ x" |3 |* `& N
# Y5 Q) ?7 S: r0 G
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
3 [+ o, W4 a0 u! I$ a
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

冒险解谜游戏中文网 ChinaAVG

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

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

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

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