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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
( R6 Z5 Q8 N/ d/ g/ T, x8 j
: z% x* x3 D9 |. d6 E6 M: m! U这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
, a9 k+ A4 O5 x5 t7 f因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。' W* G4 w% M- }5 g2 ?
https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081& ]# B% C0 |# Y
第1处3 n7 K, O* |4 x9 A% c4 Y
  1. void sub_451474(char *a1, ...)
    ) [- u+ v& D9 q+ I
  2. {1 {: x6 M& s; Q/ {" W7 _8 C
  3.   GLsizei v1; // eax
    ' b  Y- S5 ?; r( m
  4.   char lists; // [esp+4h] [ebp-800h]- k/ M1 b; ?3 x0 N. s3 y, V
  5.   va_list va; // [esp+810h] [ebp+Ch]
    : K" [0 c3 r$ Z2 h, g, \

  6. 4 A" C5 |% q8 z* {( Q& z
  7.   va_start(va, a1);
    1 Q: k0 ~4 |7 M8 L; Y1 e$ _
  8.   if ( a1 )
    & w4 x3 l& y; E. }
  9.   {
    + ~4 `( i1 Z  v# `
  10.     vsprintf(&lists, a1, va);
    ( \8 I+ b( _! @8 v, w
  11.     glPushAttrib(0x20000u);& I# a0 D. d+ r' E/ ?6 w
  12.     glListBase(base);+ v# B$ e8 ?# P5 o/ O# H: Z0 n  U
  13.     v1 = strlen(&lists);+ T6 d% L6 k: t, o  n2 [6 H' z# {
  14.     glCallLists(v1, 0x1401u, &lists);
    ) a+ Q, _& m" M( c0 p7 A- f
  15.     glPopAttrib();' O) G- D( H! x& R' I
  16.   }
    - K4 _# d7 s% M( V# M  a  ?
  17. }
复制代码

+ ~( R/ q4 L6 Y7 ?0 k, f, [; M

+ q# L- z0 E; V& s, o" B第2处. `! [' I1 B9 l0 R* h/ Y7 k" F
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    3 ^" c2 z0 U' |0 |; p* {
  2. {. D! ^. `0 b) @& |
  3.   int v4; // eax1 o& M* M# j2 I9 T$ B
  4.   GLsizei v5; // eax% @( ^8 b+ s. v( v9 o+ u6 d
  5.   char lists; // [esp+4h] [ebp-800h]
    * N$ e" _# W% v- K  f
  6.   va_list va; // [esp+81Ch] [ebp+18h]6 c/ k# z) P: q$ t" a

  7. # f( }. {; _  K% ~; Z6 u. G# a
  8.   va_start(va, a4);( `% l- f" P# b9 e1 C2 R3 N( j) n
  9.   if ( a4 )0 d4 Z6 T4 m6 X; N. U" a8 G
  10.   {' }; Y3 C7 p- M" c
  11.     sub_44F8A0(a3);
    9 G4 t* I* x8 l, d
  12.     v4 = sub_40BB44();5 T( D- e3 W' c; \
  13.     glRasterPos2i(x, v4 - a2);5 ~6 n: v" G0 }; k
  14.     vsprintf(&lists, a4, va);9 r1 y- Z8 u8 @! C
  15.     glPushAttrib(0x20000u);
    * `% E/ i, H1 E  U6 f
  16.     glListBase(base);
    - H+ }5 E+ O$ \4 r
  17.     v5 = strlen(&lists);4 X4 w+ L6 l2 u; K) `
  18.     glCallLists(v5, 0x1401u, &lists);2 i  Q. B0 n5 }- r
  19.     glPopAttrib();! ^6 e, j+ @8 X  C6 X. v
  20.   }
      C# V( n; m; B+ o
  21. }
复制代码
. `, [& x  f& D% @! b1 e; w

; R) C! ~2 K' \
7 k: f8 v1 P, R% E第3处
( Z8 ?8 R: y( c  U
  1. - @+ F: q+ F8 ^) Z) Z* h
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)* L* N8 Z: j: _  T
  3. {
    ( v1 J  o( J6 X4 ~' b3 _9 |  S. F; v1 y
  4.   GLvoid *v7; // ST08_43 x* y  y( S, H6 V' \, d* l. c
  5.   GLsizei v8; // eax
    ) [9 ?2 M. f+ }! F
  6.   int v9; // [esp+0h] [ebp-1018h]' r& E2 l! N. X2 V
  7.   char v10; // [esp+8h] [ebp-1010h]% I. c$ j( N- V0 s; l
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]" G. e9 B$ @: J4 Q; A$ z1 I. l% p
  9.   char v12[5]; // [esp+1013h] [ebp-5h]! `: l- F, r; |  m5 U8 H, m5 v
  10.   va_list va; // [esp+103Ch] [ebp+24h]. x; B, ?# T, N+ P6 o0 ?
  11. 5 M* ^5 n0 }: ^& N  c
  12.   va_start(va, a7);
    * F3 Q- d( @, f. j  r9 d
  13.   v9 = 1;
    / N( ~0 h5 K; c/ }' W& B" A4 |- }
  14.   if ( a7 ), j, n7 d& z! m
  15.   {
    & B* N; p2 D0 F2 ]: G4 ?: T1 l& M
  16.     vsprintf(&v10, a7, va);5 {' H, q9 V2 G1 T" A4 K
  17.     glPushAttrib(0x20000u);
    4 J1 c  ]- L1 `6 B9 s
  18.     glListBase(base);
    3 b& k$ O9 i" m0 v/ \% c' X# z
  19.     lists = &v10;( S* a2 k, ^% a$ G7 e& q
  20.     do3 J  ]5 P) W5 _" [. E$ e1 o! c6 _
  21.     {
    : \! Q. i4 S- x/ ?- r3 i
  22.       *(_DWORD *)&v12[1] = lists;( j0 U8 d5 F' t8 D
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )1 x$ I4 u8 H# q/ k. D% W( |! n' ^+ Q
  24.         ++*(_DWORD *)&v12[1];" D. X: N1 P7 q- D6 A
  25.       v12[0] = **(_BYTE **)&v12[1];
    3 I6 L. ]" {# W0 O  A) O
  26.       **(_BYTE **)&v12[1] = 0;
    ; z- p7 x3 b/ ~7 \( L4 f5 O' W
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )' k& r4 G" _/ Q% [- \* Q" F
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;$ s; u. w" e+ B0 m5 J5 r, V) m
  29.       y -= a5;
    8 b" W& H$ V& Q4 v( K* y
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);6 m7 C6 |7 K8 |2 F
  31.       v7 = lists;$ a8 M2 o. I6 O, i
  32.       v8 = strlen((const char *)lists);: _$ n7 X+ P4 U& D
  33.       glCallLists(v8, 0x1401u, v7);
    / h5 e: D, |( u
  34.       if ( v9 < a3 )2 D  a, Z6 H  ?' V- Z5 f' S5 l
  35.         a4 += 4;/ D; g3 O0 k7 v6 p! y" A' f4 x
  36.       ++v9;
    ! w/ \5 F4 t2 u9 A; h% j9 f" |+ {
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);. I% ?) k" G& {2 t
  38.     }  q1 O$ t2 w% p, z- a
  39.     while ( v12[0] );9 _7 B, L0 B; N1 G" x3 w7 _
  40.     glPopAttrib();; M+ O( i9 h" ^& I* [; v
  41.   }
    " x! C2 A* l. m2 q  K4 T  i8 c' V( A5 Q
  42. }0 H2 X& E: W2 C  A9 U0 ]4 D
复制代码

! L( T( V8 s* N3 `* b调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810' j! o8 t* s1 z$ e- Q
; V( F9 f  w1 y
  1. .text:004512B1 52                                         push    edx             ; char *
    5 O$ c) j/ \' r7 E: q( w) A: J
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    $ v0 }7 d, c$ A0 M! Z/ S" X2 `7 V4 z
  3. .text:004512B5 50                                         push    eax             ; base: T$ V1 q: m( B5 J5 @+ }
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    $ z; E! c7 L4 x3 w5 _4 K9 _4 \
  5. .text:004512B9 51                                         push    ecx             ; int
    ' ?  J$ {0 y) d' _' J
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]
    5 t0 [( B4 ?0 ~/ X7 u1 s
  7. .text:004512BD 52                                         push    edx             ; int7 w8 g  q6 o: ^4 n* t
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]: o( K+ b6 s2 ?' R8 L$ h
  9. .text:004512C1 50                                         push    eax             ; int
    6 s: ~& y. Z" E
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]' f5 s) N" }' i' x3 ~. y
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    $ X  z, f, `2 R. u( R
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]4 F4 W& I! ^# {6 }! r$ @. ^' Z
  13. .text:004512CB 51                                         push    ecx             ; y
    ) e% X) p4 s% }* Y# B- Z7 p  \
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]) U; i  l7 c: W8 T- {
  15. .text:004512CF 52                                         push    edx             ; int
    5 t+ v7 M1 Z( H: c& N
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码

) e3 e8 v  z/ bchatGPT整理过之后,如下- M& M+ r2 u$ G9 C0 u6 i' V; V5 w
. g) I0 [, b! T
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
      ]) k) l3 C" r, ^
  2. {
    ) }+ C' I7 S. {, C  M/ i) v
  3.   GLvoid *textData;         // 存储字符数据的指针
    6 x. F" C4 k. d1 p5 {
  4.   GLsizei textLength;       // 字符数据的长度. L* O7 T3 f  a% x  t3 h' x. D
  5.   int lineIndex;            // 行索引0 `" @* c" D" {1 }
  6.   char formattedText[5];    // 存储格式化后的字符数据
    2 {+ r7 s5 Z# B9 M0 z
  7.   GLvoid *currentLine;      // 当前行的字符数据指针" L4 `6 Z+ [5 [/ g
  8.   char buffer[5];           // 字符数据缓冲区! A& T; Y1 _5 [9 e
  9.   va_list args;             // 变长参数列表
    6 ~$ c  t4 z' n/ b3 q) D8 d
  10. % f9 Z0 ^% n/ ]$ w( Q' U( A6 ]
  11.   va_start(args, text);     // 初始化变长参数列表
    ( n, D8 [0 D/ e0 Z3 W* m
  12.   lineIndex = 1;            // 初始化行索引为1; Y. t/ e9 ^  Q2 J% q- [* d+ z. h
  13. 7 a! W  o$ L% _' i/ V# Z
  14.   if (text)                 // 如果文本不为空- S. E5 Q& \. f5 R: R5 @6 b8 k- p
  15.   {
    % x8 d0 }; O! j7 |2 W  J
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中
    0 a+ V" j0 u. U9 t
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态3 x7 N  L# ?6 u; i
  18.     glListBase(displayListBase);          // 设置显示列表的基础值+ Y( Z3 h- }- Z* W* E- K6 }4 v
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
    ) u7 t4 K$ ]6 }; u0 C2 ?  J
  20. 6 Q" t( a, r) r. J4 F7 K+ D
  21.     do
    1 o- B  z7 D% d, {0 a- ~2 ?- L4 d
  22.     {
    ; v3 e. v0 z9 t4 U5 m
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素4 |5 ?0 _9 }. G; B) c

  24. # C" V5 I! q. d- ~
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束. L# r# l& M4 ~
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    ! r7 t# D, K! d
  27. 8 W. P2 G* U- d$ K9 @
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素( E# T8 q% ?( A, z. v8 p+ Q, Q
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符; @% h* I$ a/ i
  30. 4 H$ S* a# Y$ P  M$ c
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)  E) [$ b- u! b6 J
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符& S; p1 C) w# o3 G# N1 D/ N! {3 ?
  33. . J' M* \* H  I( X' R
  34.       yOffset -= lineHeight;                // 更新y坐标# a, \( y0 e4 w: p; |% ?' R- Z7 `
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    : a8 P+ z3 T- Z9 v
  36.       textData = currentLine;              // 将textData指向currentLine
    6 [% x4 O5 T. u" `2 Z5 G6 Q
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度0 H. \! }! S' Z2 G9 w& ]
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表( f6 `; t7 _+ D  R8 J& G
  39. . a9 G4 _) Z& w9 S& Z  _1 a
  40.       if (lineIndex < numLines)2 |( T, ]- A% a2 g
  41.         lineOffset += 4;                   // 更新lineOffset, L3 d* L8 Y. p$ V3 f7 G0 y: G
  42.       ++lineIndex;                         // 递增行索引
    ! D( I; x! c7 h" f& s' C4 {9 ?% u. G
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    # B8 \" e8 E. o1 ]. l% p
  44.     }& {7 d8 y6 s) e6 n+ R. o
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    6 C7 P" e0 Y0 j% k2 u1 @
  46.     glPopAttrib();                          // 恢复OpenGL属性状态
    1 ^$ J6 L# n8 J1 }7 S
  47.   }7 @8 E  w* ]" d" N' u
  48. }
    3 L7 I1 ~1 w3 Z8 ?/ a( a
复制代码
) R% G% w+ L5 o4 T2 K7 U
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
1 m& q/ c) X1 T6 _8 B2 S% r
1 A4 v) d) s$ @int xOffset,      字幕的x坐标& [- {9 g/ ?' P6 E9 Z7 }, _
GLint yOffset,    字幕的y坐标
* p+ T5 n; i2 k! h: `int numLines,     字幕的行数(较长的字幕为2,一般为1)6 \8 a4 g; _0 m6 i+ O
int lineOffset,   这个需要再研究
4 U* i+ A' h4 \& D# D& A/ w9 c3 Uint lineHeight,   字体高度(或行高)3 a8 i" P! [$ N. h) r
GLuint displayListBase, 这个字体对应的base值
* m0 A  V& T+ u7 S2 K, ochar *text, ...         字符串
4 Q- D  P0 `9 R# v3 j5 t
% n* _# [* l3 i
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
  m4 a; n5 p+ 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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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