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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
. @$ l" ^" s! A  E" l2 z' i8 ~/ h! p9 N! N1 _* G+ C/ s8 E
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
; S% `+ q1 A$ U; [因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。( F. ~5 }  `$ L2 ]
https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
5 [9 R% E0 [" ?$ c第1处% o1 f" h0 `8 M5 ^: r" q/ ~+ Q
  1. void sub_451474(char *a1, ...)+ V9 J+ Y( J- H
  2. {
    # b$ X% Z" N- K5 v
  3.   GLsizei v1; // eax/ Z, Y9 @+ U- J+ {9 e8 U
  4.   char lists; // [esp+4h] [ebp-800h]; R0 e0 k/ z) p' ~' b- B( v3 X+ \& x& b
  5.   va_list va; // [esp+810h] [ebp+Ch]
    # g* c  k6 L+ ^2 a6 ~' s
  6. ( x" i0 O4 o* F& E
  7.   va_start(va, a1);
    5 v+ B7 W5 a2 a5 c
  8.   if ( a1 )
    $ ~7 v9 a$ ~3 L) j9 W# H8 \: U
  9.   {
    " l7 j' s0 i' |9 ^$ \2 A' {  D% f5 M4 c
  10.     vsprintf(&lists, a1, va);' {/ ]& T' `. g7 v, S( V9 X
  11.     glPushAttrib(0x20000u);! B9 u8 _- g9 e$ p
  12.     glListBase(base);/ T1 |  [# W0 x- b4 e; C1 H
  13.     v1 = strlen(&lists);
    & n& D; q- m$ c1 q% q
  14.     glCallLists(v1, 0x1401u, &lists);5 s, R7 n3 \5 J
  15.     glPopAttrib();
    8 t- O5 w9 B2 X" {* q+ d& P- M) ~' e
  16.   }
    2 q2 x  b% `7 E' X. M, ~
  17. }
复制代码
; n2 G  h6 N- q0 @
* n5 ?5 Z4 ^* i# B% ?' v' Y

/ q7 a" s8 a) e/ N第2处9 V# l, p" @0 _/ Y; x; K2 G
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    & o9 c+ C; l" E
  2. {
    4 [; L3 o# L$ [) M+ l' [' {* X1 W; E- C
  3.   int v4; // eax( |0 f0 W7 P0 U) s8 `$ s
  4.   GLsizei v5; // eax  q# ~& c" L$ S& F8 x1 a* M3 O
  5.   char lists; // [esp+4h] [ebp-800h]$ v2 m+ e- q3 D9 g0 d! E4 o
  6.   va_list va; // [esp+81Ch] [ebp+18h]8 ?2 Y: i0 D4 g7 M+ e$ T
  7. ( G$ \+ {; k/ q/ }" k
  8.   va_start(va, a4);( S! N7 x; Y7 Y
  9.   if ( a4 )& ?2 f$ `5 \3 t3 X% M( S: H( d: @
  10.   {
    1 Z- a! u1 A6 }$ K% ?$ F$ i
  11.     sub_44F8A0(a3);
    ; {* `# ]/ h' a
  12.     v4 = sub_40BB44();8 D0 x: A$ ^5 J" E* h, ]
  13.     glRasterPos2i(x, v4 - a2);
    ) l9 u6 \( i7 k3 ]
  14.     vsprintf(&lists, a4, va);
    " a6 H& ]2 F7 ~" v& e* c6 n
  15.     glPushAttrib(0x20000u);3 q! d. M* P' {1 H2 e. m
  16.     glListBase(base);
    0 E& U9 d5 |" l+ n( O" q
  17.     v5 = strlen(&lists);4 ?6 z: N: ~7 {
  18.     glCallLists(v5, 0x1401u, &lists);9 G, r/ p$ i2 U5 A" E( l* u
  19.     glPopAttrib();. k% z# |2 \+ F( n
  20.   }$ U" q& f% g% T4 v$ R
  21. }
复制代码
% t5 r$ O3 f! {% J; i
2 g5 q# A$ k- G' J, k' i) E
% \* H6 `: N' [& d6 ~- k
第3处
+ B3 j2 x; O/ U4 n/ [  z

  1. 3 ?7 A( i2 y1 ?/ b; m- B: k
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)9 n) D$ e! \( C
  3. {; N/ U8 `5 h% Y& }0 [# @- h! _
  4.   GLvoid *v7; // ST08_4& h" G# M2 G0 T; s) C: x& a
  5.   GLsizei v8; // eax% ]7 Y2 y( u- [% V8 p. D
  6.   int v9; // [esp+0h] [ebp-1018h]
    / r+ [+ U1 q% n8 m# r+ C: v1 p2 n+ x
  7.   char v10; // [esp+8h] [ebp-1010h]0 |& h$ @" s) j& `
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]9 m3 f' _! D' S
  9.   char v12[5]; // [esp+1013h] [ebp-5h]
    9 W. o2 Q$ x( z0 u; N' r' I
  10.   va_list va; // [esp+103Ch] [ebp+24h]% H+ j6 H) i" @, i
  11. 5 [" H$ `7 @0 R  A6 @8 v  z$ `
  12.   va_start(va, a7);" n! h& b0 z# N, p, `, `0 ^5 L4 \" k- [
  13.   v9 = 1;3 C$ U; L% `' d% P5 L' U9 j# N2 z
  14.   if ( a7 )( E) u0 q/ Z0 b9 S/ F& y5 U! N
  15.   {: k/ z$ a( O( ~. \" j
  16.     vsprintf(&v10, a7, va);+ L, w/ z7 k% L7 `3 _) z: F# p
  17.     glPushAttrib(0x20000u);# b+ v1 C( I* N* \, g1 z/ Q+ i
  18.     glListBase(base);
    + e' F' Q; g; S, P" C
  19.     lists = &v10;  x; D% d! ~5 B
  20.     do
    . p5 e' j0 V, B: Z4 Z3 P
  21.     {
    : b/ b6 O, f% f, C$ E+ r& r  n
  22.       *(_DWORD *)&v12[1] = lists;2 U& S: w( N. ]3 x
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )
    ) s) r, \% q0 U. [4 v
  24.         ++*(_DWORD *)&v12[1];  W# ^+ q7 X" S% c
  25.       v12[0] = **(_BYTE **)&v12[1];
    , z0 Q3 Y" m* v) Q: _
  26.       **(_BYTE **)&v12[1] = 0;3 p. D. F0 y3 g7 `7 \$ J
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
      U# {- ?0 a  q, f& ?2 @
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    / l  q7 D0 O% b
  29.       y -= a5;/ P5 @& H! Z/ z0 N1 |1 P) j
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    # Q( R& s7 e4 ~
  31.       v7 = lists;6 t( r  l1 s& `( h! i% n: I+ Q" m
  32.       v8 = strlen((const char *)lists);8 r3 u2 @+ r7 q% Q, G9 F
  33.       glCallLists(v8, 0x1401u, v7);- b" ~5 {* e/ G5 a3 d6 o
  34.       if ( v9 < a3 )4 ^! H4 T  g3 @$ s& y9 t/ C
  35.         a4 += 4;
    5 C: y) Z, e* q4 l9 \
  36.       ++v9;
      R3 I8 r. o! ?4 x/ j
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);7 z6 N0 e# d5 y/ |
  38.     }  y: p) y4 @0 F2 f4 m" Y& e" K% y
  39.     while ( v12[0] );' [8 [+ P; w6 k* X5 F, l2 ^0 U
  40.     glPopAttrib();
    # G( Y4 I2 ~9 K" d9 E
  41.   }# U1 U' u& C" |
  42. }
    ) h7 w" c2 T) q; O9 I  n9 C
复制代码
" V. Q$ e7 A2 D& t
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
9 p. y( S+ ~( u; j. {8 A
# h: H1 G( e4 ]5 M& L4 g
  1. .text:004512B1 52                                         push    edx             ; char *
    * o8 A: x" _/ g: t7 f
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]# V/ K# m6 t2 r. K8 a
  3. .text:004512B5 50                                         push    eax             ; base
    4 G1 Z+ t8 ]6 t, d+ Y7 I
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]# `. O  j" j3 i$ _9 U
  5. .text:004512B9 51                                         push    ecx             ; int% U' a# x7 c; Z) B5 |9 @
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]; u. U6 _$ ]+ T) K8 p4 {( v. A
  7. .text:004512BD 52                                         push    edx             ; int( D( f* }6 B6 h
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    + _( a0 K* n6 Q6 Q. S
  9. .text:004512C1 50                                         push    eax             ; int
      z8 E9 A$ u/ V) N" i4 N: ]
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    6 L% w; q- F8 H( Z# T* ]9 c
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    - Z- z# M9 u  Z$ i. F% Y# p
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]5 g* `  Q% j. s: l$ j  V
  13. .text:004512CB 51                                         push    ecx             ; y5 o8 Z+ `0 B* {: ?9 |8 W
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]& ?, g2 D4 G- d; N
  15. .text:004512CF 52                                         push    edx             ; int
    & Z2 [4 b3 h3 Q! `
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
( a; R( ]$ C7 H1 |
chatGPT整理过之后,如下( N8 t, @& Z6 Z' Z! z
( l! g8 \' V7 k: B) j. j7 v. f6 ^# E
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    ; L  |$ _# d% L7 z1 l
  2. {5 a- K; @7 e% }; g
  3.   GLvoid *textData;         // 存储字符数据的指针+ a6 K7 l; g$ }  F: v9 Q
  4.   GLsizei textLength;       // 字符数据的长度
    : M8 P' i$ G6 T  T+ g
  5.   int lineIndex;            // 行索引
    2 o  m) e+ c8 p; e0 v0 h
  6.   char formattedText[5];    // 存储格式化后的字符数据
    ! u, m- U/ _* Y+ V
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    5 G8 E8 }" ~6 Z/ z2 X) ?0 d* F
  8.   char buffer[5];           // 字符数据缓冲区+ {5 f) p# M- z0 s. m7 l
  9.   va_list args;             // 变长参数列表
    - o" O, f8 j! I4 \% \+ T! {/ g: ?  j

  10. 1 P# r; e! F$ ?' Z# r. i
  11.   va_start(args, text);     // 初始化变长参数列表
    ! D& w; A% V, `( J5 l$ @: k% t: N
  12.   lineIndex = 1;            // 初始化行索引为1
    , f0 d5 D2 M: a* ]! P) p  H% |1 n# w

  13. - K: x4 i2 M3 W+ l1 u
  14.   if (text)                 // 如果文本不为空
    1 A2 Z. k0 r& @
  15.   {9 F. \" E' r$ m0 M9 v3 S
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中+ i$ l8 z! `) H+ v; \  B; F- A9 C) Q
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    / n; u  l, x; _6 r: Y# v
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    # }7 p4 V7 t3 C9 u
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
    ! L7 D: v: @* m  \. k
  20. 5 x, f2 Z4 @+ l+ v3 J  d% _/ \
  21.     do
    0 C- y: @: d$ ^' {$ W
  22.     {
    1 V7 J: v, v# \3 C% B( B5 M2 R
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素
    1 _  J& q1 q/ b( _. Z; ]
  24. 0 y, S4 c+ i( @4 W1 O( A$ ]
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束4 z: ?8 G; g9 g/ ~5 [3 g% @) S
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素: H' q* I% d: W' h8 ~# G+ e
  27. $ Q% ?5 ]( W4 S! H
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素, i8 |8 G* c8 R3 n+ [: w
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符' J; @7 A- F' L+ y9 w" O

  30. , n# b6 B: v; {9 _
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    4 k" |, u# m/ H! c% N$ L+ ~
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    : P/ u/ D3 N, u* ~

  33. 2 f( t2 U! w1 x. [+ c& L
  34.       yOffset -= lineHeight;                // 更新y坐标( y# G# e+ ~" m% |
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置2 b1 L3 s- b+ U
  36.       textData = currentLine;              // 将textData指向currentLine
    * e6 j; E/ q+ }! }
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    $ t0 l( Z6 _) Y, S" M9 G
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表1 a7 X2 x/ W2 E9 v, g& K; @; V

  39. : v, x7 {0 @/ k$ j# R6 x9 e) ~
  40.       if (lineIndex < numLines)
    3 k+ K$ F& [! `1 ?9 Y, ?& H' B; q
  41.         lineOffset += 4;                   // 更新lineOffset: m2 W5 x  k$ M3 t/ x, u" g
  42.       ++lineIndex;                         // 递增行索引" B# h  a7 A& V2 p  \& [' Q
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据. |# @" p: {  H( J0 Y# r3 r
  44.     }
    6 l2 t0 ]2 U' t; S
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    7 i4 B2 L5 {" y4 M6 V
  46.     glPopAttrib();                          // 恢复OpenGL属性状态
    2 P$ H. O) L' u5 M+ P1 l
  47.   }
    ; J9 H/ K) Z# }/ t- g
  48. }' m1 ^) y; I; A4 w4 Y
复制代码
& i8 F$ D( K* P
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
7 w2 h; u6 K! ?7 J; C) r% G/ \! Q8 h, w
int xOffset,      字幕的x坐标
6 {) |! P5 u3 P4 ~9 _2 E. }. n+ qGLint yOffset,    字幕的y坐标
) \% ^* l3 d" Cint numLines,     字幕的行数(较长的字幕为2,一般为1)
  Z6 v& g1 `2 x) aint lineOffset,   这个需要再研究
% |$ w; |8 C: z) Bint lineHeight,   字体高度(或行高)* O/ b6 U) O* V1 \' d( b5 f; h
GLuint displayListBase, 这个字体对应的base值
( Z' M7 L7 ^' X! j$ \* V' Lchar *text, ...         字符串
: v1 x! P0 d2 L( `7 ~' a0 z1 F1 ]- N( n3 H
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
- n4 C' |4 q5 }  x
回复 支持 反对

使用道具 举报

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

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