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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
$ u, h$ W. P$ j( v1 ^; G% R1 x% d( u2 N
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎8 r# A8 b; K' J* k$ a' [7 W$ t
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
9 L" b2 r$ W/ t# r6 I3 K* [https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081" ~9 m5 {2 f2 z+ A
第1处8 r" g9 _% I( B/ W& G6 }) ^
  1. void sub_451474(char *a1, ...)$ P/ X) l+ g" H' Y2 z9 }
  2. {
    3 _- Z% ^, p  \
  3.   GLsizei v1; // eax
    : V* B  a: Y$ v) R
  4.   char lists; // [esp+4h] [ebp-800h]
    ( l* J, B) F& ?5 Z& G+ D4 R  ~
  5.   va_list va; // [esp+810h] [ebp+Ch]( o/ U* [, \9 S

  6. 7 Y+ P# b. G8 s1 S4 `, O- i
  7.   va_start(va, a1);3 N$ d7 _, M; \' l; \
  8.   if ( a1 )( I" x! L! ^3 E0 ~7 K
  9.   {
    : m5 K. a! m1 [- C( f2 H$ D. i* z
  10.     vsprintf(&lists, a1, va);
    2 R2 i) ]6 I9 U4 y
  11.     glPushAttrib(0x20000u);
    ; A6 q1 h6 T* h: O
  12.     glListBase(base);
    ' S- ?5 y! a" T
  13.     v1 = strlen(&lists);) k4 X8 C! l8 F# w5 x, h4 Z; u
  14.     glCallLists(v1, 0x1401u, &lists);9 I* x# W' T( E$ r" C! \% O
  15.     glPopAttrib();
    ; v) `" M6 A4 S% E
  16.   }, u+ d5 ]2 v) a# D1 P+ b2 {
  17. }
复制代码
7 W: A- F( H3 E( p( j

* W# g5 C; Q3 Q1 F/ Q# Q  F1 y; A) G% z& b
第2处
1 j% G, S( l- Q& C
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    5 p4 M" F' ^( M
  2. {
      ?6 p% u- |, Q( }% x/ Y
  3.   int v4; // eax5 ^+ ?5 N2 L' z/ j8 ]1 W) M
  4.   GLsizei v5; // eax
    : Y: P. J& o3 p: Z# t& t6 \
  5.   char lists; // [esp+4h] [ebp-800h]  j# J7 f. F' ?/ D: ?
  6.   va_list va; // [esp+81Ch] [ebp+18h]- v) j4 R& P7 A% }. l5 P# c' m; ~
  7. ' e* f6 J8 Y. C/ v/ x! J6 ~3 s! G/ x$ D
  8.   va_start(va, a4);
    . O/ n- v3 P1 B7 C7 t" w
  9.   if ( a4 )
    / k  w+ z  \: H/ F$ T# M/ f
  10.   {) {# i  ?/ @; k0 J2 r
  11.     sub_44F8A0(a3);
    . a8 Y8 _; N/ F: Z: v2 E2 t% E
  12.     v4 = sub_40BB44();4 ^; i' K0 m& D1 I* R7 V
  13.     glRasterPos2i(x, v4 - a2);
    + Y! t" s4 j2 L" {' O
  14.     vsprintf(&lists, a4, va);; K8 Z1 E; _" Z
  15.     glPushAttrib(0x20000u);
    / N/ n/ w; g. ~) a. x: ?5 F" h
  16.     glListBase(base);
    + ?( x9 u5 B1 N/ A
  17.     v5 = strlen(&lists);+ L" g: J. u: p
  18.     glCallLists(v5, 0x1401u, &lists);
    2 b2 ]4 m, v+ A0 }& E2 @7 g
  19.     glPopAttrib();' f& x% t; s* H
  20.   }6 _( @! ~6 q4 o* w1 X0 A
  21. }
复制代码
0 J7 d" m7 ^+ M6 K9 g& Z

# N! ^: D: V8 p& s
% _% ?, S9 R' F" d第3处$ D, Z, A; }8 Q1 {/ b2 ]

  1. 1 ~" X: q9 q/ o# g9 K) K! J1 u+ d9 @  a
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)# @1 N. g; g  d
  3. {3 l) u2 ~9 Q1 t$ x5 @* \1 ?1 G4 g
  4.   GLvoid *v7; // ST08_41 d* j$ x3 j4 t6 r! i
  5.   GLsizei v8; // eax
    $ ?: o, H6 I" ?4 x9 @
  6.   int v9; // [esp+0h] [ebp-1018h]! ?! a3 e1 @3 `" l! P2 y# ^
  7.   char v10; // [esp+8h] [ebp-1010h]+ b1 S! r4 K# ?
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]1 u* A9 Y5 c: r
  9.   char v12[5]; // [esp+1013h] [ebp-5h]
    " o* Y# E+ R1 E+ E8 a! [; d' \
  10.   va_list va; // [esp+103Ch] [ebp+24h]6 h1 N9 K0 J# {9 H; s, G6 T: v9 Z* [
  11. 7 X9 M8 e( f% s7 h
  12.   va_start(va, a7);" ^) m( P2 W0 I& S: T. w& U
  13.   v9 = 1;
    6 r' [6 R# q0 J
  14.   if ( a7 )
    . B8 c8 g$ K; _" ^! q7 r
  15.   {
    7 d% R7 T( x2 T1 S" J
  16.     vsprintf(&v10, a7, va);
    9 p' d5 J# Y8 H
  17.     glPushAttrib(0x20000u);; M$ n3 J/ b5 u! w
  18.     glListBase(base);6 \- F) S- h- y" t
  19.     lists = &v10;3 d% e" X7 ~: e# s3 \  R- G% ~
  20.     do! _, p, o; X2 [9 M- J$ X  C
  21.     {
    8 U5 V( h" s2 s1 W$ M
  22.       *(_DWORD *)&v12[1] = lists;
    . A5 ]% c7 u  w) i0 H$ u/ R
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )( G, Z* W( m# d) w6 B
  24.         ++*(_DWORD *)&v12[1];
      p1 y% {/ g" O
  25.       v12[0] = **(_BYTE **)&v12[1];" u" l+ j1 [& _
  26.       **(_BYTE **)&v12[1] = 0;  s- M* o8 X$ y/ X0 g/ G
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )# N) k+ c, I, y% u7 A( e- n* @
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    6 I2 P4 r+ P9 K; M
  29.       y -= a5;
    5 d* ?0 M3 s0 K8 S( l. d
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);9 h# n% C7 ^3 T% S' t2 L
  31.       v7 = lists;
    $ D2 W& ]3 P* O& K/ g
  32.       v8 = strlen((const char *)lists);
    , Z# b! n$ g/ P! n
  33.       glCallLists(v8, 0x1401u, v7);
    - l/ a# T- p% N  ]3 _
  34.       if ( v9 < a3 )9 x) w" b4 n" D" T
  35.         a4 += 4;
    7 L1 n" _! d3 m; [) o$ F9 s
  36.       ++v9;
    2 E; \4 r% e7 A+ z4 _9 }
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);2 R1 k/ p( D( v. U' ?* n" u
  38.     }. g2 ]. n4 \* u9 o0 F. C6 k7 i6 H
  39.     while ( v12[0] );
    ' v& m* n4 t! R$ g6 v  T) G2 d
  40.     glPopAttrib();5 M% K8 P- m/ q6 b1 v
  41.   }
    . n5 U' u, f# ~  a- ?
  42. }' u4 K- D# L3 [, F! W5 |
复制代码

, H' ^) j, j! D/ J4 _# F调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_4518101 ~2 c0 l: U" w

# g: Z# u7 l% k1 Q8 m
  1. .text:004512B1 52                                         push    edx             ; char *
    + O9 w& ?2 x; o4 k( x( a8 [
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    # ^, {0 `/ ^) s! X! j
  3. .text:004512B5 50                                         push    eax             ; base
    2 Q+ B6 F* \2 V! n( _* P" [9 b
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    5 k1 A, h. m" O- m/ \
  5. .text:004512B9 51                                         push    ecx             ; int
    , Q8 f% d  u+ c4 Z' T) E& a+ {
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]: e) n' ?: }9 X& L4 \2 I: l3 I+ p
  7. .text:004512BD 52                                         push    edx             ; int
    0 L# e: P9 D6 }# x. T/ E6 y
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    ; q1 \  K3 L7 i5 {
  9. .text:004512C1 50                                         push    eax             ; int
    ' b- ^5 w! p+ M" u
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    1 f  q7 J; a  ?3 P( C
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    # \4 W: i' W  D7 {( L
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    " ~+ D6 f  G7 I6 _$ z
  13. .text:004512CB 51                                         push    ecx             ; y
    ( ?* f) B5 f, E5 R2 G
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    : B3 n! R& s% A" K8 V
  15. .text:004512CF 52                                         push    edx             ; int
    ! ]! e( I- J, [6 s0 U7 _/ G
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
0 g0 y/ a+ e! M1 c$ |5 m8 x
chatGPT整理过之后,如下  P& b0 b8 v$ {2 L4 D- `
% g4 c# f) [" g8 E' I! O
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)% W$ G- v" W, V. K1 }
  2. {( l' u7 A3 c- ^8 m" A4 R  O- ]
  3.   GLvoid *textData;         // 存储字符数据的指针
    ' Q7 b/ a5 I# G' u1 O7 i1 Z4 U
  4.   GLsizei textLength;       // 字符数据的长度+ u8 V0 ^( a9 ^5 k1 z
  5.   int lineIndex;            // 行索引
    5 Z9 G9 V9 p* y$ q% a
  6.   char formattedText[5];    // 存储格式化后的字符数据/ W4 a. _  a2 Y5 Y9 y
  7.   GLvoid *currentLine;      // 当前行的字符数据指针% C5 S7 I5 V4 X/ h7 G9 N  p
  8.   char buffer[5];           // 字符数据缓冲区8 l8 G9 s! h( d- ~/ }7 f0 W2 P
  9.   va_list args;             // 变长参数列表
    * o0 z% M& @8 I# c% |: V

  10.   {) G6 x) R3 |3 j; a5 J6 R; M/ ?
  11.   va_start(args, text);     // 初始化变长参数列表; u& K, v9 r2 Y  D8 _
  12.   lineIndex = 1;            // 初始化行索引为1
    " @7 Z* U- g1 |$ s* f$ \: t& D

  13. ( x% b2 h6 P% J! j! D$ o
  14.   if (text)                 // 如果文本不为空+ V$ N4 w) S7 ?. ]
  15.   {
    / [& W% o8 X& Q
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中& Y) s" {# w  g" A7 P$ Z2 ^
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    / b9 d( \8 L. \9 m3 A2 z9 k* B
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    ' ~+ E. |7 T3 K
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置, \4 T. T$ f/ P, T9 Y% ~# Y! d

  20. $ ?$ [9 I$ e3 [
  21.     do
    5 V1 z1 g! L- D$ l) J7 u
  22.     {
    + O$ `- A( n( G$ C% N
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素- t6 r( [0 s  q; R! F8 g2 @; \! {
  24. , ]0 R9 n4 U$ n- N
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
    6 y0 w+ h1 [( Y5 Z1 `/ Q. o
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素  H) n/ V' x9 h' ]. T3 A
  27. ( z6 m  G! X' z  P
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    9 b( a5 d2 ?% E. e" i3 F2 N4 g) @
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符
    + |5 I6 y/ q; }1 b

  30. " R! H; T) m. L7 O" I0 W
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)& t4 m/ s  L+ M# E. |8 {
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符0 L' I  Y! A+ C( I* [2 m

  33. 2 p4 d4 m( p# L* ^, m* ^
  34.       yOffset -= lineHeight;                // 更新y坐标/ F" Q1 d6 k2 X7 t. N. F! P+ Q" b) S
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置3 F, {' F; ^+ i- ?3 k
  36.       textData = currentLine;              // 将textData指向currentLine6 d* b) n5 X- d* O" t
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度( ?' F  T; [% x! [# e' e! s8 S
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    . b9 Y# W4 H) |/ v& w1 u& B& A

  39. 2 W/ j# u! }* a& w- Y( I' r
  40.       if (lineIndex < numLines)
    1 A: [& x! t6 R
  41.         lineOffset += 4;                   // 更新lineOffset3 u! `& H/ u# t; x
  42.       ++lineIndex;                         // 递增行索引# y, T6 B5 e8 ]6 }9 _8 Z' |
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    & v, h( d4 ~* L. N8 o) y
  44.     }
    0 G" T& g! i8 Y
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
      ]/ A& Q0 V6 N& o
  46.     glPopAttrib();                          // 恢复OpenGL属性状态8 E& ]' Q" p! s6 @! }( {0 [
  47.   }0 {9 D/ m5 y1 H% }; u& f7 e
  48. }
    ( p, G/ b. }+ x
复制代码
" d0 l8 v' ]+ p1 A$ g1 y2 e
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
0 _# N+ _. i( S! J9 R  e
4 l- y  K/ P) Zint xOffset,      字幕的x坐标
/ a8 v  ?6 `+ ]GLint yOffset,    字幕的y坐标
2 H( z/ m; T! \int numLines,     字幕的行数(较长的字幕为2,一般为1)2 n7 T  A1 j6 w/ T/ C
int lineOffset,   这个需要再研究
* o! ]* D( o: h" D; f$ l& qint lineHeight,   字体高度(或行高)8 e4 l: T! \# X& |- ]
GLuint displayListBase, 这个字体对应的base值( P! Y. z" H' Y7 v
char *text, ...         字符串
8 \* [$ g/ U& T
. _, o  [9 K9 H# ~: V
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
- \" E7 r1 _9 j( ?5 ]' p
回复 支持 反对

使用道具 举报

高级模式
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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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