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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
# e5 ]3 a3 y( y7 I' z1 Y: b" u
  D4 v: V* }, L) Z; J+ O9 Y这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎0 T4 x$ l/ Z7 `4 P1 T+ O. p$ z
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
4 V1 H9 a# |, S! i, k6 k: Jhttps://www.chinaavg.com/forum.php?mod=viewthread&tid=1540812 k( u5 \9 i/ T, l! u3 t
第1处5 y- H! z& v2 |4 g
  1. void sub_451474(char *a1, ...)
    ( @+ X6 Y' K3 l% z! T9 H
  2. {
    - {4 x: U( S  w3 T- B; J
  3.   GLsizei v1; // eax
    2 e8 h3 w! z9 o) `+ w
  4.   char lists; // [esp+4h] [ebp-800h]
    % K: O, ^# ^, y, W( W* W
  5.   va_list va; // [esp+810h] [ebp+Ch]
    9 r1 a& m9 Z0 H
  6. ' U) i0 V" v% d0 e5 m& _0 |2 ^
  7.   va_start(va, a1);
    + U8 }. e0 S+ E
  8.   if ( a1 )
    + v1 e1 b- ^/ t$ Y2 c2 G% {# y* u* j
  9.   {; E- v- K, [- a3 k. O9 z4 o- s
  10.     vsprintf(&lists, a1, va);
    + ]: Z2 ^( G7 R. @- c
  11.     glPushAttrib(0x20000u);: o/ U, }, W6 g1 v6 r
  12.     glListBase(base);: K9 w, k& P0 o" R$ G" M7 L' A
  13.     v1 = strlen(&lists);
    * C# |- y* d& D, K, `. {) E
  14.     glCallLists(v1, 0x1401u, &lists);
    8 y  H) S! l8 p2 T8 e( Y, h) b
  15.     glPopAttrib();
    8 B3 N8 F; N$ L! U
  16.   }
    # h% l2 V  Y3 z
  17. }
复制代码

+ L; h8 B7 Y8 i% q  A4 v! J6 f6 h8 O# g  T# p# Z8 T. |
; d3 d+ O5 W) `, a
第2处
7 P. x! A. V5 j, O9 P) I( x4 ?
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    7 m, A  a% b" l: K; I3 q+ X
  2. {
      R0 ]0 i3 K1 o# R
  3.   int v4; // eax
    7 n" t% ~' X) D9 ^% s8 F
  4.   GLsizei v5; // eax
    7 O. t) w+ _6 ?. J# G" y0 J% o8 u; H
  5.   char lists; // [esp+4h] [ebp-800h]9 W) L: Z' s& y$ Z0 g0 w( u
  6.   va_list va; // [esp+81Ch] [ebp+18h]8 Z- U3 e4 \6 e5 t" O! h5 _" ~
  7. % i5 `& s8 k, ?% I
  8.   va_start(va, a4);
    1 }" {6 \/ }: T+ [7 D' ^
  9.   if ( a4 )
    $ n, ]! @! X- K
  10.   {4 f% K$ R- S6 _% j- z  V* w
  11.     sub_44F8A0(a3);
    : V: v1 k7 K0 @- d3 \# f
  12.     v4 = sub_40BB44();
    ) X1 @: M. Z0 s$ f6 H9 B
  13.     glRasterPos2i(x, v4 - a2);& s- v; S0 p0 `  y8 q" i
  14.     vsprintf(&lists, a4, va);
    . b" t& G# o( k; e
  15.     glPushAttrib(0x20000u);
    8 U  l. x7 v" L& i) y& C
  16.     glListBase(base);
    + B- B5 s- Z! g9 a" F! s# W
  17.     v5 = strlen(&lists);
    3 X: x  ]+ [' w% D! x2 v
  18.     glCallLists(v5, 0x1401u, &lists);
    + Y" G6 N1 b) W7 p
  19.     glPopAttrib();
    0 f/ @, N) E0 T! ~
  20.   }
    ( |1 M: Q% q7 k% l$ g! a
  21. }
复制代码
' H1 O+ b5 z- C# L1 c1 \
0 I4 J5 N' f) N/ l% ~/ D8 v
, e& {1 i6 ~8 U* C4 ]
第3处
6 u$ _5 N4 f3 x3 i/ T9 Y& n

  1. 2 w; J! T2 v- T. l9 R1 E
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
    0 W/ M1 _2 q7 p( |' i, u% t
  3. {
    4 ~3 A- {) l' \6 ?0 k
  4.   GLvoid *v7; // ST08_4" P4 I2 u6 O/ V$ _% y
  5.   GLsizei v8; // eax' A. i7 G& u7 z: z0 w
  6.   int v9; // [esp+0h] [ebp-1018h]
    " m# l! k' ?" Q$ }7 t
  7.   char v10; // [esp+8h] [ebp-1010h]  |# g- C# U+ ~' ]3 a, ^: [
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]  U4 n+ `9 `0 U# x9 N$ U
  9.   char v12[5]; // [esp+1013h] [ebp-5h]; n  g% E+ c: i. b; z2 D' F
  10.   va_list va; // [esp+103Ch] [ebp+24h]' h1 F1 R' B9 }5 i9 l
  11. + X3 n7 Z6 I& S; h! Q7 E
  12.   va_start(va, a7);
    & ?& ~) z! d8 h; [. n5 ^+ t
  13.   v9 = 1;
    " t! J) N5 z' t& Q" S  J
  14.   if ( a7 )+ i' M& R! _5 x3 p" N) G. |2 B
  15.   {  c6 z+ |/ M/ G0 L. E* l
  16.     vsprintf(&v10, a7, va);% T) ?/ S" ?4 h( C+ \, s9 ^! L7 |
  17.     glPushAttrib(0x20000u);6 Z4 ?0 l7 z" a
  18.     glListBase(base);
    / W+ i( X1 v/ h/ l, I" k
  19.     lists = &v10;
    1 Q) t2 W7 L" i" M
  20.     do
    5 |" _! Y% Y; B1 x! Y
  21.     {
    , V% z3 m" p0 @: f- a
  22.       *(_DWORD *)&v12[1] = lists;2 S6 D0 J1 M) @2 L. l# P
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )) I4 N9 f' O! f  c5 K/ u. D
  24.         ++*(_DWORD *)&v12[1];
    ) Y0 g- n; `5 Y8 Q) C. V9 C
  25.       v12[0] = **(_BYTE **)&v12[1];$ f8 {1 s4 G2 r9 p5 P9 M
  26.       **(_BYTE **)&v12[1] = 0;0 m- P, @0 ^- W
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 ). X' b) A& K9 z" {
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;  p! }; N. R- s
  29.       y -= a5;
    . R2 x& m0 a+ y! q
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    2 N+ Q9 n5 I  t% G  n7 A% ~
  31.       v7 = lists;
    - g! A% ]( R# ?8 w- w; ?( a# {! l" s
  32.       v8 = strlen((const char *)lists);
    ) A# O) Z( ~, S% `3 S
  33.       glCallLists(v8, 0x1401u, v7);
    2 Q2 H+ {. `% Z) c' M& @9 C
  34.       if ( v9 < a3 )0 ^% Q1 r- r/ {' v& A5 e2 R0 P
  35.         a4 += 4;
    / r: ]4 z2 r0 a! y% J- N# u: I
  36.       ++v9;
    $ N; ~4 p  v( o- d5 Q
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
    + N( B* d  z1 q% M, [" T
  38.     }
    1 ]# F; \7 q6 j- \' N
  39.     while ( v12[0] );5 {0 Y9 S' c" d+ I: J& k
  40.     glPopAttrib();
    ! c: J4 o, a/ S5 |# d! S1 |: d
  41.   }
    " C' X6 v3 f9 Q/ |6 k  q! G5 Y' y
  42. }
    * L& m( C, I# ~! e4 o
复制代码
: K" O% P7 U& o- X
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810/ t% n, g% T+ {: b  j$ d

# p! z. A( ]7 Q8 I9 ?3 f" Y- g+ S$ V
  1. .text:004512B1 52                                         push    edx             ; char *
    $ p" O1 g+ q# n* U# u
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]$ X# j( D( L8 {7 |) ?/ P; }
  3. .text:004512B5 50                                         push    eax             ; base
    : _+ \% N9 t3 Z( V6 |6 Q) z5 Z
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]: [' ?) b- }7 k( z2 N- K: g
  5. .text:004512B9 51                                         push    ecx             ; int
    # [/ v! X  o$ T8 F0 @( v' H7 G
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]5 c8 C3 W3 c0 r. R5 N: ~
  7. .text:004512BD 52                                         push    edx             ; int
    ; E; X% `8 [. Q5 k" e: L
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    " w. l& i4 D0 v) a: f: M6 d
  9. .text:004512C1 50                                         push    eax             ; int
    & v+ q5 t$ i9 w0 t  F) n7 t6 i
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]# P* I3 I  k: y" o
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    5 K1 }4 w" n+ m% v, n8 [; _7 M
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]) t( T! B$ I" ]) V5 P
  13. .text:004512CB 51                                         push    ecx             ; y& G: c! _0 g3 m( A, h
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    8 z+ ]: y( g# a0 Q, j
  15. .text:004512CF 52                                         push    edx             ; int
    & L! B  D" v" e' C
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码

/ }0 E0 n8 |9 P5 Q2 @; l2 p& CchatGPT整理过之后,如下
- t& K0 y' t/ V" u! r" C4 ^; S/ S) ~+ ~
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    6 \! x! y6 k4 O
  2. {; U, ~1 C& ^' w, _
  3.   GLvoid *textData;         // 存储字符数据的指针
    7 h7 V: G3 Q: N  b' H- q$ w
  4.   GLsizei textLength;       // 字符数据的长度: R  G2 {% G+ p! z( f( I
  5.   int lineIndex;            // 行索引
    : ^3 F! w+ z; g" G6 F6 a5 w
  6.   char formattedText[5];    // 存储格式化后的字符数据
    * y. Q1 |. |: \$ K  I  N" l
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    4 q, I) [, n4 a4 s" G% C, O. p" n
  8.   char buffer[5];           // 字符数据缓冲区  I, A+ [1 T8 z1 [" x
  9.   va_list args;             // 变长参数列表; w6 g4 e  K7 P, s
  10. 6 q! y$ n' M1 L% V7 u& f; \
  11.   va_start(args, text);     // 初始化变长参数列表
    ; H6 w: r0 K7 k1 w( [% [
  12.   lineIndex = 1;            // 初始化行索引为1
    ( k% g$ d4 K- b) y
  13. 4 S8 o# Y6 h% D# U2 p% b! H
  14.   if (text)                 // 如果文本不为空2 B: J9 V: Y, a5 a( U% c, u4 F
  15.   {8 s  W/ t1 k, x; X  z5 [9 C7 e
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中! K' ~( b- G! R3 `
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    , g$ ]2 I5 C$ W$ ]* G
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    * }& W# n4 n5 q4 N3 h$ t
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置/ t5 _, y7 ^" k# P- o6 ?
  20. 1 n1 X. B9 W4 f" ^/ ]  ]0 a4 ~
  21.     do
    / ]- m9 V8 G2 y0 i6 ~' e) Q6 l
  22.     {
    5 I7 d! ~  ^6 X+ T5 E2 N3 g
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素
    # u$ q/ R3 \" D/ u( i9 E
  24. : M( \1 |! M5 `, X4 ?
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束! S2 z( g9 O5 P0 T
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素# y: L( ^3 y9 O

  27. & ]- A' w7 N! C3 @% i4 |
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素5 J" k8 _6 X9 ?" v
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符
    0 w% O% a5 s8 t4 b
  30. ! g( k5 s/ W4 G- h. _% a) B4 t
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)9 ~$ k* M3 D7 S( N5 l8 O% }/ m
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符1 b6 z  v6 m; g: p; F8 [3 a& b

  33. 3 ]% L7 W- {3 o. |
  34.       yOffset -= lineHeight;                // 更新y坐标$ H4 u* K8 P% X
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    3 F  y: n( `2 C
  36.       textData = currentLine;              // 将textData指向currentLine% n% I' x+ s0 f' H0 v3 l
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度0 }+ a6 V: \+ r
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    : J1 p' X: P% k/ f7 P
  39. " S' |/ |9 v& f' l2 Y& t
  40.       if (lineIndex < numLines)9 J9 j/ [% z0 J# ~
  41.         lineOffset += 4;                   // 更新lineOffset" A5 L% |) @- O9 ?7 r, I
  42.       ++lineIndex;                         // 递增行索引
    " z9 Y4 i+ Y: `
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    8 z4 K6 ^* t0 z; q
  44.     }  K' L0 Q" e  W6 a- o
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    6 g+ a7 k) r6 O. G
  46.     glPopAttrib();                          // 恢复OpenGL属性状态
    3 T2 t& y1 F+ |5 d. s' ]
  47.   }
    3 r5 r3 M2 v  w" C
  48. }
    2 W2 F: X8 w) j* e, g  j
复制代码

& A' D$ X# [) L含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
# J7 G9 b! z% Z
! |1 h; F) E( t3 V1 N" Cint xOffset,      字幕的x坐标( B- W+ f9 ~  O3 K8 w! U( r
GLint yOffset,    字幕的y坐标  X, E* H& v  L* \+ R' x  l# d
int numLines,     字幕的行数(较长的字幕为2,一般为1). F" p- E7 W/ U5 J' l. d* y& |
int lineOffset,   这个需要再研究. n: j8 v: d+ h+ E8 F
int lineHeight,   字体高度(或行高)! V/ o2 w) s! o. Q) s
GLuint displayListBase, 这个字体对应的base值* {5 `. U3 a  }$ t# M1 Q
char *text, ...         字符串
- v. E+ K) H7 c: o# Z% }" f8 e
1 f3 Y9 n4 E( Y; P. E
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来$ m. X; W! R6 C, X. n
回复 支持 反对

使用道具 举报

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

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