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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑 ! y: t# B* Y  S+ k, {
- b! n; A& ~" P/ [7 Z
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎8 I, T, z) q, K& h. u" O! V
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。' \8 z& e* I* D( b3 l% X
https://www.chinaavg.com/forum.php?mod=viewthread&tid=1540811 h, k+ c- g8 b2 _$ ?
第1处& P, K0 G& C+ r
  1. void sub_451474(char *a1, ...)
    , L4 w0 Q1 {; g+ W) }+ A' T
  2. {5 Z4 Q- u: p, f% l7 ~9 X. \4 I1 B
  3.   GLsizei v1; // eax
    # u- b. V% y+ P, E% [, L+ `
  4.   char lists; // [esp+4h] [ebp-800h]
    $ Y. x2 B' C! b+ V( P, z9 c0 e) B  I
  5.   va_list va; // [esp+810h] [ebp+Ch]% S4 j: ^7 `+ ^

  6. 5 Y/ w# n7 r: z9 J/ @
  7.   va_start(va, a1);
    ' N3 l! G3 G9 g- J$ r. P
  8.   if ( a1 )6 @( }6 t2 h3 {- Y0 }
  9.   {& b, h8 d- {& t( q7 X
  10.     vsprintf(&lists, a1, va);
    * k9 C* Y& C# H
  11.     glPushAttrib(0x20000u);
    - s, C6 X2 Z& p, c
  12.     glListBase(base);
    : F  F9 Q6 J/ Y/ F* ?8 [  E
  13.     v1 = strlen(&lists);
    1 W8 y  P1 `7 M! ?. Q
  14.     glCallLists(v1, 0x1401u, &lists);
    ; }5 ^' h7 A0 Y6 U+ o- N* }
  15.     glPopAttrib();
    ! Q5 F, z5 S0 t% B0 `  W' z0 j
  16.   }
    1 E6 U: e) G. o/ Q! f
  17. }
复制代码
# E( J' u. N' v. N

) @; d4 @2 j  @# |( J0 `/ O: O0 J! e7 ~2 Z$ p7 C1 D: e
第2处2 s9 [, M6 P" l! O/ G
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    6 d! C! F+ d8 E: {
  2. {
    2 }' R6 ~6 }  {' ^8 g6 z) D1 F5 D
  3.   int v4; // eax( O. G8 Y( J. k( t- w1 t, G
  4.   GLsizei v5; // eax
    4 q8 {5 C& U5 R( S8 F6 A: y
  5.   char lists; // [esp+4h] [ebp-800h]
    # O& P( P( ^! W/ ~
  6.   va_list va; // [esp+81Ch] [ebp+18h]
    & E: P, ?, S+ ?6 A

  7. ' ~1 h# H# O/ w# C0 I# b
  8.   va_start(va, a4);
    $ ]9 @2 D" C2 F% p4 S
  9.   if ( a4 )( R! j" D/ b) g6 Y/ R2 p( z- H
  10.   {
    / Y" P8 G7 l, X! M5 R/ d* w, b
  11.     sub_44F8A0(a3);
    / `4 v+ o, ]9 Z! l2 F2 h
  12.     v4 = sub_40BB44();
    8 L# z' G4 l5 U9 e2 c8 O& z7 k
  13.     glRasterPos2i(x, v4 - a2);
    1 M' v# e2 U6 g, B7 b
  14.     vsprintf(&lists, a4, va);
    / o8 P0 ?1 j; U8 a. ]
  15.     glPushAttrib(0x20000u);/ }0 S) N) Y" Z9 x. q
  16.     glListBase(base);3 o+ z! x0 F5 ^0 X
  17.     v5 = strlen(&lists);, V( r2 [/ ?# q% W. g0 r
  18.     glCallLists(v5, 0x1401u, &lists);6 E& n  W) t8 ~& y, u
  19.     glPopAttrib();
    / N' W( `* [# \
  20.   }7 M$ H0 q+ E; v4 i* L" W7 t3 q
  21. }
复制代码
; k2 I' E: J( p, f

* C  |1 ~4 U8 q9 A
7 ~9 P6 h; W9 N! q: y0 l第3处# e4 S2 z& p. F4 Y) p* H

  1. ( o) \" x- i3 r, O) _$ B" L; c  g
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
    & Q3 Z  q$ G! k3 J. S) _6 @! ^3 N
  3. {
    : k+ i3 Q, b# ?' j( t1 e+ T
  4.   GLvoid *v7; // ST08_4! E* C( {. @0 S3 a; l+ `' v
  5.   GLsizei v8; // eax! N7 U+ f; a# \
  6.   int v9; // [esp+0h] [ebp-1018h]
    # Z) j7 L  ?7 x; ]8 c4 r
  7.   char v10; // [esp+8h] [ebp-1010h]
    ( f4 F2 n" d; ]* t1 S& C
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    , y; R5 e3 Q9 D) l- ]
  9.   char v12[5]; // [esp+1013h] [ebp-5h]# C5 R; ^) k6 j, C0 s
  10.   va_list va; // [esp+103Ch] [ebp+24h]( _$ }: t1 s/ |

  11. ( N' m- P3 U) y
  12.   va_start(va, a7);. Z- D- c# G6 g" m# t
  13.   v9 = 1;
    , F* |! ^3 {; B8 u' T
  14.   if ( a7 )( }" h' d4 |3 M2 v4 u0 }
  15.   {
    $ q' Y$ m! p) e
  16.     vsprintf(&v10, a7, va);
    ; L& |9 W% \# i8 m) ^& v
  17.     glPushAttrib(0x20000u);3 g; h% j7 l) _8 u$ [7 h3 `* `
  18.     glListBase(base);  y1 V7 _3 d1 y# [& ]  m- E
  19.     lists = &v10;. }9 b$ t* t; L2 r# F+ b4 x
  20.     do
    - q. Z" k9 K/ U7 H1 ~: }
  21.     {
    ; z4 _' K6 K9 R7 k9 Q1 k
  22.       *(_DWORD *)&v12[1] = lists;
    3 a" i$ W, P+ U0 h
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )
    0 j4 d0 M- _$ d( c& f
  24.         ++*(_DWORD *)&v12[1];; l% P* q5 W4 I- R+ L1 H* ^! n
  25.       v12[0] = **(_BYTE **)&v12[1];+ j: D5 i" n4 [" A% A6 {, k  @1 I
  26.       **(_BYTE **)&v12[1] = 0;
    2 O& ]0 |, h; N  [( g( q  Y
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    1 K8 s( y9 y8 r
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;7 ]+ h8 s: e4 R6 f( N
  29.       y -= a5;
    6 a8 D5 M/ i  q
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    3 o1 ?4 B5 s5 P" n' W9 J1 F
  31.       v7 = lists;
    ) g; Z; @* `! {/ F
  32.       v8 = strlen((const char *)lists);
    7 ~& n6 _: x. w; Z
  33.       glCallLists(v8, 0x1401u, v7);! n. g! n3 p0 b+ n0 |
  34.       if ( v9 < a3 )
    ! F+ i5 C9 f% g" b! J
  35.         a4 += 4;6 \& d3 L, b& _. n6 r1 U
  36.       ++v9;; q0 O, V- o: i, u; r  E" Q! d
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
    : T- U/ U7 H: a" O2 }% ]- D" r
  38.     }( S) @* [# O) }& x9 g6 J$ n
  39.     while ( v12[0] );
    2 Z8 t: w( e7 L% I7 f4 V( e/ H
  40.     glPopAttrib();9 h" ?& Y5 y6 r: a2 g0 H4 O# ]+ I
  41.   }; O# s) c. m2 k+ D' A9 @" O6 \
  42. }9 `/ M: Z# d( D$ [
复制代码
; R4 e9 n, c9 z1 ^0 J  A
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
$ ^7 @! _# F. H& c* F, t4 ]# c
$ M- @7 G4 Z) B/ U- Y; v
  1. .text:004512B1 52                                         push    edx             ; char *# e, U3 ?& ~7 x5 A: o+ ?, v/ e6 E
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]  q. s3 j+ b  S* n
  3. .text:004512B5 50                                         push    eax             ; base, Q- g$ G+ ?/ t! d; _' ?
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    * C0 Q5 |9 |( y$ h$ r, ?( s
  5. .text:004512B9 51                                         push    ecx             ; int
      n- Y( c+ v* T( a- W5 n
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]
    5 ~6 g7 H' U+ ~
  7. .text:004512BD 52                                         push    edx             ; int5 O  ~1 m$ h( I' C4 w3 U
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]$ `' x) {7 `2 W$ u
  9. .text:004512C1 50                                         push    eax             ; int
    ' U; H7 ]% |3 k. }
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    3 F4 y, `3 {/ f$ _1 Q+ V# W
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]- q: P& K5 A6 E% c% K
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]$ M4 P+ @0 K" W! @# h) h
  13. .text:004512CB 51                                         push    ecx             ; y2 c2 T, k$ X: y
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    4 p% P& m& a, Q) I% D) y" j+ l
  15. .text:004512CF 52                                         push    edx             ; int
    9 g6 `  w, ]" g
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
7 ~# e0 j2 K  ~" e* x2 A7 K
chatGPT整理过之后,如下( E, ]; J0 B7 d( d, t: k

0 B# r! K" F1 N
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    0 [+ y8 M0 `2 W
  2. {
    4 Z& K, A- M  i% {- I: T
  3.   GLvoid *textData;         // 存储字符数据的指针5 c  B1 v. L' t3 l$ N6 ~* X* @
  4.   GLsizei textLength;       // 字符数据的长度$ I6 w) D" {6 |% h( L" a6 E% W
  5.   int lineIndex;            // 行索引
    . |" C4 @! ^5 u. }2 y. R
  6.   char formattedText[5];    // 存储格式化后的字符数据
    ! t3 Q, G7 a+ J! `9 n9 a5 w
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    + ?8 f' {7 s) q2 K: }# Q& Y  ~7 G
  8.   char buffer[5];           // 字符数据缓冲区
    1 h7 Q5 V3 ^/ [3 K' O
  9.   va_list args;             // 变长参数列表' v6 i$ g  P* Y4 ]2 O1 t* F+ e

  10. & w5 |0 s6 [1 Q  S  }6 n
  11.   va_start(args, text);     // 初始化变长参数列表6 {0 J1 ?& S: B  l
  12.   lineIndex = 1;            // 初始化行索引为11 u- ~" Z9 w) F1 U9 X) c

  13. , B- s. s% J. z% n4 z3 e9 p6 ~
  14.   if (text)                 // 如果文本不为空
    / Y# g- ?' V  o3 y( N. k% d
  15.   {8 |, O- B: n# U1 U& _2 z
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中$ _" u( R4 `9 w7 n- _
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    ; P& Y: m0 _$ |* N: K
  18.     glListBase(displayListBase);          // 设置显示列表的基础值* }2 [, T: o' r# A" X- s. T
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置! ^; O% J; Y; f5 D% v0 ^6 T. Z; I. T
  20. % p1 ~* n: ?. C, h+ \; r, T
  21.     do
    ! Y: I- n2 C) e, j0 W' D: p
  22.     {1 @6 R! _. E- x7 O
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素
    8 U% }' F8 i4 c* p4 j* |. ^
  24. * ^% @' V+ T1 H( x  \/ b
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束/ \. Y2 p$ @: f
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素2 C$ i) O+ ?/ v! r
  27. " n! t0 B# [3 ?/ X6 W& ^
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素0 G% Z$ k& f' T+ K
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符5 U$ t, R2 W, T' q- v
  30. ; F. h+ M2 T) t- L
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    : R4 V- n$ B+ y3 G1 f( \3 ?
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    / ?* u0 l- q! |5 B- c" n( _

  33. ' M+ J' [* K' f& Y" Q8 [% f
  34.       yOffset -= lineHeight;                // 更新y坐标
    3 Q, D# I+ D4 N1 t
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    & s! u5 u5 n6 B
  36.       textData = currentLine;              // 将textData指向currentLine
    . M, k  ?4 n$ J5 \: F) c
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度" S. i& [1 l/ `) k, \  M4 l, I
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    * P! F- ^7 D( l" N0 x& V1 ^/ ?7 U
  39. - `8 k( |% u; L4 l
  40.       if (lineIndex < numLines)8 b2 Z- D4 ?7 _% S2 G, T9 g
  41.         lineOffset += 4;                   // 更新lineOffset
    + Z5 W& f& a" U- _
  42.       ++lineIndex;                         // 递增行索引, l& c  e- L# ]
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据0 R6 S) `8 A4 \1 f# F1 ~
  44.     }
    * t6 E  p! W8 s( S0 `( n! {$ M! j
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环2 z% V& W) d1 u2 f$ o1 H( E
  46.     glPopAttrib();                          // 恢复OpenGL属性状态
    1 a$ r) P) P  S
  47.   }' N% O) p) ]/ A+ }
  48. }
    . q  V, x& Y6 Y0 W) ?2 w
复制代码
+ A5 n4 m. o% a% E  @' r! z7 P% Q1 M
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前& a  ^  c# x6 s& E4 p7 w/ D: S  U3 [# _- s

0 V. ~0 b, h  F( v% |1 {2 U( w2 T2 h* Qint xOffset,      字幕的x坐标3 x" G4 j/ h* w
GLint yOffset,    字幕的y坐标
% s( m* W2 R& j! wint numLines,     字幕的行数(较长的字幕为2,一般为1)
* r* n& z. D* _# o5 I9 aint lineOffset,   这个需要再研究
% V8 L% N, F. C  r8 mint lineHeight,   字体高度(或行高)1 v4 b$ w+ L' [, d1 @# n# }
GLuint displayListBase, 这个字体对应的base值* z3 ]4 r7 t0 w# l
char *text, ...         字符串
) s3 o6 u* m# `' O. k, e- A+ y: x- j. q2 U3 N( v) l( i
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

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