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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑 + q3 B* I4 W7 S4 r/ @4 x; X

/ u/ H0 e5 v# q* C: ]这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
3 @2 Z, H1 F  h/ i. ^因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。0 z7 w. X6 Y, @* }
https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
1 e* Z5 W+ f2 `- }  ^第1处
8 g) [8 \: x$ E! v
  1. void sub_451474(char *a1, ...)0 U+ ^& |) W" {$ w
  2. {
    % e' @/ Z4 w7 J. H
  3.   GLsizei v1; // eax! y3 E# v1 Q, u; Z
  4.   char lists; // [esp+4h] [ebp-800h]5 o: }" F# d/ ^8 n( `% ]
  5.   va_list va; // [esp+810h] [ebp+Ch]
    * d0 r3 B6 w) r+ g

  6. , N3 S8 ^" r4 L. N. G3 f6 u
  7.   va_start(va, a1);& N) B) j0 c% {
  8.   if ( a1 )
    ( }/ ~* O4 \& L: [
  9.   {# G8 c4 l( H- b, A# v6 \
  10.     vsprintf(&lists, a1, va);8 N. S+ K# Q# M% ]: O
  11.     glPushAttrib(0x20000u);$ |$ s) J4 T# Z" F: G/ Q
  12.     glListBase(base);
    . u0 N+ l# c. O+ d0 g# ?
  13.     v1 = strlen(&lists);
    ; h4 g: }6 L' [. q4 R6 X+ S" k
  14.     glCallLists(v1, 0x1401u, &lists);0 g1 c  a  s* a6 R# k' L
  15.     glPopAttrib();! V6 v5 ^8 C  M% Y7 l% g  a. W: K
  16.   }( Y" h5 j8 a' L! }
  17. }
复制代码

6 _4 B. Y. n+ S
( a6 h$ g/ N1 T$ Z% d+ n
3 ~, q( J' Q" r. V. j7 j4 H第2处+ \) S) N  Y) \8 ?5 z5 V
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    " ]% Y8 t- s$ Q, z4 @8 e7 T' a/ \
  2. {* ]2 `0 i6 Y3 Y8 u
  3.   int v4; // eax
    ! O% \; I0 @2 {$ {
  4.   GLsizei v5; // eax$ ]/ x! D" K5 Q9 i- i
  5.   char lists; // [esp+4h] [ebp-800h]3 _. I; L, d0 B! ?; u
  6.   va_list va; // [esp+81Ch] [ebp+18h]5 n& P8 k* g' _& m3 |7 \
  7. 1 ~/ p, ~+ ?/ i8 d1 N7 z
  8.   va_start(va, a4);
    $ w, w- H- ~7 b# v
  9.   if ( a4 )! i, Y+ v, x- h$ I" k$ \$ a# z' I$ ]
  10.   {
    + u/ V. B& u# V6 l; M5 f' ?/ J
  11.     sub_44F8A0(a3);
    0 k& ^6 [" t' }+ |% M
  12.     v4 = sub_40BB44();  V! F' u7 G7 n9 `9 }: m% n" X, F
  13.     glRasterPos2i(x, v4 - a2);
    ! t: r+ m  l1 f) x& W
  14.     vsprintf(&lists, a4, va);8 V' L( M- f8 ]1 ]! V! s$ E, S' d
  15.     glPushAttrib(0x20000u);$ T5 [$ r* Z( h0 |; a  @6 {
  16.     glListBase(base);
    / Y2 t, V- h; Y4 P* W4 L$ T
  17.     v5 = strlen(&lists);
    $ {; O0 L# R) |8 ?# y
  18.     glCallLists(v5, 0x1401u, &lists);
    ! m( e( }2 j; S! ^1 D& F
  19.     glPopAttrib();
    ' Q; Z+ {) V- I6 Y0 i# m
  20.   }) d3 r; ^6 Z: S% {% n9 }
  21. }
复制代码

9 X3 ^$ F  \4 Y9 s; }. m) ]0 o* J- E2 S1 Y; U% {8 |- X# @
. @7 u  h& R- W( s/ ]* I/ k
第3处4 Q2 j  w8 D8 h" s
  1. 8 N/ y1 |" k4 o" e' r
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)4 Q  D; o7 ?) S4 T/ j6 b0 d' s
  3. {
    ; a5 T0 f7 U( T4 o) S% m) e
  4.   GLvoid *v7; // ST08_4
    8 f, T; z# w: I% \8 w
  5.   GLsizei v8; // eax
    & b4 D3 d* f- R0 O% x/ ]. p* H4 u
  6.   int v9; // [esp+0h] [ebp-1018h]
    & q9 S- S# V+ |* ^9 R
  7.   char v10; // [esp+8h] [ebp-1010h]
    + J  U1 {& \: c8 `2 e" F) n- ?7 ~' Y4 T
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]( C8 h! {) q4 z, W) k, B* c! M
  9.   char v12[5]; // [esp+1013h] [ebp-5h]
    9 x( B4 z% b& {7 l' l
  10.   va_list va; // [esp+103Ch] [ebp+24h]
    & ~7 m/ g) |: ]' s# B

  11. 3 u0 q! p4 k! C7 f& u4 N
  12.   va_start(va, a7);
    , N+ h; B: @: F5 X) N
  13.   v9 = 1;
    % j) k5 }) V' U+ T! |
  14.   if ( a7 ), t, j; Z4 U) y1 s7 ?( ~; i% q
  15.   {% F( e  D) G: g  M7 r4 r* t2 a0 k/ O( S
  16.     vsprintf(&v10, a7, va);
    ( m7 O, P5 ^- @3 l3 h, U
  17.     glPushAttrib(0x20000u);
    + M7 W- X4 X/ a! d& j
  18.     glListBase(base);
    0 C+ |5 b; Q$ q" y. e5 H0 B, i, Z
  19.     lists = &v10;  n1 Q: m' B. c. ~5 V* Q* p7 ]
  20.     do1 a4 x% d2 f3 }5 o+ M  Q+ J
  21.     {
    " {' f2 a( y/ ^* P" g
  22.       *(_DWORD *)&v12[1] = lists;
    # i; w/ Y0 V( Z. S
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )6 U$ [) f! A8 e7 ~9 p( X& O
  24.         ++*(_DWORD *)&v12[1];6 p/ r$ d& J- b$ n
  25.       v12[0] = **(_BYTE **)&v12[1];
    $ c0 N  r( _0 a# y- X: B4 U( |
  26.       **(_BYTE **)&v12[1] = 0;0 e& o/ S) e$ S
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    # p0 ]: L# {' o. q5 C7 @
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    % e6 I5 k, G! j1 }' E- t/ [# A
  29.       y -= a5;
    7 O  D) i" `2 `3 \* \" c
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);& T$ ^! d' |1 \3 W  E2 D
  31.       v7 = lists;
    ) I& r" u' [! @: c1 P  {' e
  32.       v8 = strlen((const char *)lists);
    ; O6 {+ e/ e* F2 Z+ ?- [$ H" O/ ?2 O
  33.       glCallLists(v8, 0x1401u, v7);: n6 y; d! O3 C
  34.       if ( v9 < a3 )
    % V) w( k4 Z3 F
  35.         a4 += 4;: ^+ q& d/ S9 t; u; V; b  Y4 W. ~
  36.       ++v9;, c- J% z7 K' u& ?
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);1 x- Q8 U* E5 j# n
  38.     }0 p8 y# c; P6 X
  39.     while ( v12[0] );' o/ S8 T( A5 E9 Y6 G
  40.     glPopAttrib();
    7 h6 b0 i! h% {2 G8 g- b- t# _
  41.   }$ P- [0 u- A- E% H6 S5 ]; @9 q) B
  42. }1 X# y# G, Q# @4 R0 H
复制代码

% k8 V5 C! E4 W$ q! u调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
+ g1 Z9 X3 Y' u5 F$ L. T3 }% y, A' n/ x4 e! N( {+ f
  1. .text:004512B1 52                                         push    edx             ; char *) y* I/ U  Q6 z, I5 {# _
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    & w/ j9 ^/ T# w$ Z) Z) e
  3. .text:004512B5 50                                         push    eax             ; base
    ( k1 H$ @: {5 T# [7 s; X' l
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
      b1 @! h* n: f- @
  5. .text:004512B9 51                                         push    ecx             ; int
    + z7 v7 `- m7 ]0 r6 W
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]) p$ g5 |. z7 q/ [
  7. .text:004512BD 52                                         push    edx             ; int
    % I; t: X6 b' v' P2 a* {
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]5 ?0 R! m: i; E% `# W* r
  9. .text:004512C1 50                                         push    eax             ; int
    7 s. F' U, r) S  e
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]! u7 K* ^/ |$ F
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    ) [1 l7 r" ?3 `8 m6 M* m- X
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]0 B3 E- w- x5 |
  13. .text:004512CB 51                                         push    ecx             ; y' m& k" K1 z6 x3 S, ^8 l+ {
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]( i) r/ `: I- F4 D3 _
  15. .text:004512CF 52                                         push    edx             ; int; r( g' ]& a% {+ N7 U6 U
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
8 E, D9 l9 O" y
chatGPT整理过之后,如下* s; E) A! D) c: M
; T- T( Y+ {9 I+ ?
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    4 M* R4 ^5 ?. c" x1 A
  2. {, E' S4 Y, ~$ D: f6 n- G/ t
  3.   GLvoid *textData;         // 存储字符数据的指针! o3 c4 v4 d. g, }# F: j
  4.   GLsizei textLength;       // 字符数据的长度+ b. E* Y# I$ m& W
  5.   int lineIndex;            // 行索引
    . F; g- y1 K8 S& ?+ J; D
  6.   char formattedText[5];    // 存储格式化后的字符数据
    2 M" k- U) @5 A( a6 W
  7.   GLvoid *currentLine;      // 当前行的字符数据指针- N0 L+ y# z5 i% ?1 E
  8.   char buffer[5];           // 字符数据缓冲区) p/ u1 |. v" L! j
  9.   va_list args;             // 变长参数列表# }6 d, P# y# K, A& s+ B
  10. + x* V( W& ]& U
  11.   va_start(args, text);     // 初始化变长参数列表
    ( a& G6 b9 k% P" ~
  12.   lineIndex = 1;            // 初始化行索引为1
    & S- ?3 ~6 _( W
  13. 5 j: `$ G6 R4 u! h, J2 O# f% G
  14.   if (text)                 // 如果文本不为空
    . @6 N& x; z# l- V( g2 }
  15.   {
    4 t6 Z4 S) i& f/ }! c9 \6 ]* S
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中
    ( A# H" s+ Q3 [% B4 N. z
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态* w3 n: x* Y; X2 M
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    9 J1 V# D6 m; P( J  o; [  B
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置# j4 K& A; y3 F
  20. 0 z) q0 F/ J" M
  21.     do  r1 D( b  H) @9 F# R
  22.     {( b; t) J. ^2 G: n5 ^
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素
    & V/ F- p" C! r( R$ ~+ N
  24. 9 K3 a# |  S- [/ z7 t& _7 O# A
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束* o# e( N" \+ \+ x2 j
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素! K' j/ W5 f, b% z: i6 u/ [

  27. ; w. Y1 U+ G# B7 R) R8 A1 Y# v
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    6 G0 i2 z9 J% J+ j; s6 n
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符4 x0 n6 g) H0 r
  30. 1 T9 a+ u; N4 T7 |* I$ @9 ?/ d$ N
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    0 S( m* [$ z& N
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符4 i6 e2 z6 ?; f  ~

  33. / Q7 D$ q* k* h& O( j2 [4 ?
  34.       yOffset -= lineHeight;                // 更新y坐标8 M7 F5 z1 B& _, @
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置" _0 s7 i* V7 R" H: j
  36.       textData = currentLine;              // 将textData指向currentLine
    ( {" c3 ?9 c, i
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度6 u. g" i3 L6 P- p- S) R7 M" c- G
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    : L7 d) K9 [! H3 y& T9 D

  39. $ N8 L, ~. M0 S2 d; Y
  40.       if (lineIndex < numLines)
    7 |$ H8 q. x8 P; T
  41.         lineOffset += 4;                   // 更新lineOffset
    - i2 p  w  X! ^% d7 U. S. a" ^
  42.       ++lineIndex;                         // 递增行索引' h' H2 s' O7 V1 P; G# P( ~
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    * H0 v/ ]; o  t% E- z3 \1 O, z
  44.     }1 Q0 o* u4 ]6 i# b, k
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环4 T( b7 H$ ^* S4 v
  46.     glPopAttrib();                          // 恢复OpenGL属性状态5 K0 O& ?  n: E! p5 V1 O) L
  47.   }
    3 D; y6 I1 a6 S, d
  48. }
    ) x( M& {  |2 U3 w9 B
复制代码

! B' F: w; a8 n7 m8 `: ]含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
4 O$ ^- ?/ z8 Q! p+ A  K" @1 \
7 W+ i) t! n4 j+ M7 t6 V* N% ]4 Cint xOffset,      字幕的x坐标& l- o. @9 H& X& G
GLint yOffset,    字幕的y坐标- Z$ M. |% K( v/ l- W1 L4 x
int numLines,     字幕的行数(较长的字幕为2,一般为1)
2 c4 d7 G5 {( @" C2 ?int lineOffset,   这个需要再研究
6 N  e9 s5 D0 \& V% l6 A7 xint lineHeight,   字体高度(或行高)
  G$ z1 L- ~) |8 ~8 k. {GLuint displayListBase, 这个字体对应的base值
6 p" s" N  P  {6 `6 jchar *text, ...         字符串
, o/ ~4 X- }/ Z3 A1 E9 ~# N. x
% Q0 I* P% C/ L: b
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来. ~0 E: a$ M$ f! Z" c- f' I+ e# D7 t! t1 w
回复 支持 反对

使用道具 举报

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

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