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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑 8 i* E6 `) v9 ]$ J5 H
$ g) I6 M, j5 ^' M2 Z1 }( f  j4 w+ a
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎! p. V* `+ }1 f0 M6 Y# L
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
; U) ^) [$ U# M8 D  ]7 H, C3 xhttps://www.chinaavg.com/forum.php?mod=viewthread&tid=1540817 K; Q. L. z5 W% q, @
第1处
& v; p( F. |& e1 `4 A# z
  1. void sub_451474(char *a1, ...)
    ( E* X* K! ]; p- W1 f( y
  2. {! ?# H+ H  `% v
  3.   GLsizei v1; // eax7 D6 c0 ?( f* D/ V) u; `& |
  4.   char lists; // [esp+4h] [ebp-800h]
    3 D! l9 [- k- q. l2 I/ p* _
  5.   va_list va; // [esp+810h] [ebp+Ch]! s; x! a' S2 o; i* {9 F- g
  6. 0 ?1 _. D/ K2 S, u5 C" p( O( d9 {! ^
  7.   va_start(va, a1);
    ( q$ y% @7 V* T( F9 a
  8.   if ( a1 )
    : M& {% C6 [4 D( _! @
  9.   {
    8 V! h* R$ H2 U* N! p; y- O' |
  10.     vsprintf(&lists, a1, va);
    ; g6 v; u$ \: l- f
  11.     glPushAttrib(0x20000u);5 Y7 L" Z) |) b0 D
  12.     glListBase(base);
    & y, Y: W! ]% b0 O
  13.     v1 = strlen(&lists);
    $ W! `& s0 u* X# u
  14.     glCallLists(v1, 0x1401u, &lists);+ s& u2 w4 P' u! J! ^
  15.     glPopAttrib();% U& E) Y; a2 ~9 f
  16.   }" S. b8 [3 k% a( g! }8 R  m1 m
  17. }
复制代码
7 Y( ^" |  r* r" {8 p8 Q5 Y

0 X3 ]0 U4 x/ r% t  D. }, ^; Y" \2 e$ _0 h9 ?. K8 ?- U" r7 Q! L1 O1 H
第2处
' ?% Z# F& ~: z/ a
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)- w: s5 J6 F2 f- U1 B# |; a/ J
  2. {
    5 Z$ s! G& }6 s  f( {& v
  3.   int v4; // eax
    , k% K; M# x# O% E
  4.   GLsizei v5; // eax
    7 B) H1 U# K: x0 O) J
  5.   char lists; // [esp+4h] [ebp-800h]! Z! g+ U% i" A6 m7 @! a
  6.   va_list va; // [esp+81Ch] [ebp+18h]% s, i/ x0 w. c) X% N6 ]$ p5 \

  7. + L, H3 K: Z- a$ _6 x  y/ }; {
  8.   va_start(va, a4);
    " K0 B/ f* ]+ x
  9.   if ( a4 )$ H8 p8 ^( T. Z3 p: ]- z9 w% b/ C
  10.   {
    8 K: k/ m3 D: o. C3 s% r; w6 u/ \
  11.     sub_44F8A0(a3);
    - y" k9 h; `$ X
  12.     v4 = sub_40BB44();  R0 K9 p: G! N8 I
  13.     glRasterPos2i(x, v4 - a2);4 `" E8 ^9 b! ~& E3 |9 m/ j$ ~
  14.     vsprintf(&lists, a4, va);% @9 p8 a' q5 C! |) h. e: g
  15.     glPushAttrib(0x20000u);$ s1 L/ \- ~. h5 m4 S% t
  16.     glListBase(base);
    * _! l2 Z! W+ ?8 I. e5 O. t
  17.     v5 = strlen(&lists);9 q; v# \$ n+ G  S0 i
  18.     glCallLists(v5, 0x1401u, &lists);6 a+ `& b$ e/ e# E# o, f: Z- Q
  19.     glPopAttrib();
    ; R/ r3 z& e9 n  \! O% g! u
  20.   }
    3 M; E0 g) c% ?2 E
  21. }
复制代码

  ]- A% p% u+ ~& R5 |
( |; O  h+ z! T' r+ F2 t) j1 j* r" B6 x: \7 m
第3处; [3 {, w0 p3 i( d
  1. ) G6 C6 ?. ^8 Q. S6 S1 C
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
    . K4 i: I+ ~3 z% U) K/ @& P# M  E5 R/ T
  3. {( _' R+ ~2 H1 O# F
  4.   GLvoid *v7; // ST08_4
    0 i! {: \5 G/ L+ c& c" C5 ~
  5.   GLsizei v8; // eax
    + H2 i! S% D# I& ]' L% Z4 l8 b3 M
  6.   int v9; // [esp+0h] [ebp-1018h]) R( S, N. S7 t/ J4 s  E/ v: ?! ~
  7.   char v10; // [esp+8h] [ebp-1010h]
    * `2 K8 V2 g  z( P( W
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    ! ]+ G% G, n( Y' p
  9.   char v12[5]; // [esp+1013h] [ebp-5h]2 K' k. j% F9 h8 U( ]  q1 I
  10.   va_list va; // [esp+103Ch] [ebp+24h]' w( m! V! b, d9 @2 r& r) p2 r

  11. + u8 L) b. I; P1 P: H4 S
  12.   va_start(va, a7);
    3 N! h8 o' x4 F3 g
  13.   v9 = 1;
    6 I# R4 n  M3 p
  14.   if ( a7 )
    " Q' m6 @/ i  E0 K. a' y' [( z! Q
  15.   {
    " U# o+ j/ H7 a
  16.     vsprintf(&v10, a7, va);8 R$ N2 |3 T1 S8 [5 }' D" R9 l( s
  17.     glPushAttrib(0x20000u);
    + {5 {9 q5 x7 V( P3 C
  18.     glListBase(base);
    ) I6 o, S9 \8 R  ?# C% p3 X/ x
  19.     lists = &v10;# i; Y& i8 x- N
  20.     do$ y& D( t0 J0 i& q) H% S
  21.     {
    : d' B( F, e1 z
  22.       *(_DWORD *)&v12[1] = lists;
    7 x6 ], ?0 Q' e; A3 w0 Z
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )
    . ?9 t; W' U5 u, E
  24.         ++*(_DWORD *)&v12[1];
    3 O+ C7 W9 G+ d; c2 }3 q
  25.       v12[0] = **(_BYTE **)&v12[1];
    1 G, H1 Y/ n6 M
  26.       **(_BYTE **)&v12[1] = 0;1 X1 T& l. F% e0 a
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    . I* C: x) t2 P
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    ! \- H0 z0 Q# b2 m
  29.       y -= a5;
    . F! p1 f0 ?* a5 Z# N
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);' S: d: ^3 ^+ [  l. ]0 c; _% D
  31.       v7 = lists;
    ! f0 L0 F2 i$ i+ X! v- g3 R, @
  32.       v8 = strlen((const char *)lists);
    $ \5 i  o; d: L( G% o( U& \
  33.       glCallLists(v8, 0x1401u, v7);
    # O/ ]& W9 X* c0 d/ U" e! n- @
  34.       if ( v9 < a3 )5 w7 q; o, K5 Q+ |" X2 h
  35.         a4 += 4;
    : E. R, m7 m; G
  36.       ++v9;
    ) ^3 G/ @7 c) ]# H) v
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);1 e; M  D6 e+ s/ H% R: t
  38.     }$ b6 w5 ^( I$ j
  39.     while ( v12[0] );
    $ ]+ J& b) w. z0 i0 W
  40.     glPopAttrib();
    ) w  Q1 t% X- m" Z/ [
  41.   }
    " a9 ^: ^6 i8 a7 @( J% b
  42. }  h! p2 i: k2 G6 T
复制代码
7 y/ x0 u- U5 z4 G# M+ C3 f
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810" |3 V% X2 b8 E" _' D3 G  o
% w# d/ g1 N; N5 J1 F) [
  1. .text:004512B1 52                                         push    edx             ; char *
    / J6 [$ o5 G/ R# ~* Z6 ^
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]9 g0 a# v4 ^% L6 J9 p
  3. .text:004512B5 50                                         push    eax             ; base
    " \! h$ Y# E6 K$ I: z/ m* R4 b
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    1 S2 c4 g6 w0 Z" V
  5. .text:004512B9 51                                         push    ecx             ; int
    / z; a1 p" q* ~: ?( l3 K
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]: K/ l2 ~1 [7 M' _6 x, |, j+ _
  7. .text:004512BD 52                                         push    edx             ; int+ V! x. F( @5 }  |9 s
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]* V! [6 P( p6 P5 ^" A0 D7 y, h% T
  9. .text:004512C1 50                                         push    eax             ; int
    5 E8 y! A5 ~0 a9 Z$ [
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    / @3 S# q+ Y0 c$ {6 O
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]$ L( U" |$ n) }3 ~
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    ; n* d% I2 F2 H7 a
  13. .text:004512CB 51                                         push    ecx             ; y' J. r, q4 S9 P# [
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]( {0 H3 F; u& Z! w5 i  b
  15. .text:004512CF 52                                         push    edx             ; int. {% \! U) e; p7 N8 F; Q
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
% T4 K) }; D  E8 Y0 x
chatGPT整理过之后,如下
; N2 C$ C2 p3 c3 `$ N0 e3 w. O8 g/ B* {& \' q
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    & P. h$ @  Y+ y: o2 W* Z( p
  2. {8 ^3 t, O; J6 X0 X9 I. B
  3.   GLvoid *textData;         // 存储字符数据的指针. S- G6 d2 \/ f3 K* H
  4.   GLsizei textLength;       // 字符数据的长度1 B/ n% Z& c" Z" c/ |
  5.   int lineIndex;            // 行索引
    2 Y! p& ~+ o2 u1 P
  6.   char formattedText[5];    // 存储格式化后的字符数据
    8 {, Y2 ^- F2 i: m, M$ G
  7.   GLvoid *currentLine;      // 当前行的字符数据指针8 P/ X, n" D/ ^4 d1 Z' ~+ `
  8.   char buffer[5];           // 字符数据缓冲区
    & o. u7 c8 G% z1 T9 G/ A$ y3 I
  9.   va_list args;             // 变长参数列表, B4 C" D1 \4 u4 G

  10. : p  t& _. ?% J3 U& o
  11.   va_start(args, text);     // 初始化变长参数列表2 @- L) `% e& D( o3 E; D3 Z* ^
  12.   lineIndex = 1;            // 初始化行索引为15 j( P2 j( L, k: g7 w

  13. 0 z9 u3 p' S: U8 G
  14.   if (text)                 // 如果文本不为空
    : P: m0 p- ?1 d" |: A
  15.   {( N4 t7 H7 H" B" |! t8 u
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中9 h8 B' i4 J' x
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    0 D% o6 r) p! m2 v5 `. ]+ N+ }
  18.     glListBase(displayListBase);          // 设置显示列表的基础值. Y, h5 ^  R! ^4 x3 t& C
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
    . O& j1 o0 r5 S. B  {! G

  20. , R0 m, c- y. V4 H0 d8 K% _3 B7 s: D
  21.     do
    . Y" g! m4 U8 ?1 k' H
  22.     {# X- }! Z7 O1 a' Y2 A5 v
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素4 c8 A5 ^6 ?( N# E1 t8 G

  24. , l6 t' `  M) @# a( [/ \
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
    9 g8 N, d* L8 Y" \+ r& Y
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    . }5 g6 W& P8 n0 |4 ~" r
  27. 4 J; {# ^4 |9 a6 J/ h
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    # J% G- C: P- d/ l% {5 v9 K0 f
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符
    , P, K4 {' ]4 t0 E) M2 N
  30. ) B; p3 u+ j7 z  R% n; q
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)6 S' D! l! ]# l4 D% b
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符% ?, j: c: }: P: j! }9 e# @/ j

  33. ' b/ r9 [+ L! h$ }
  34.       yOffset -= lineHeight;                // 更新y坐标
    4 \5 u) @) U, B5 ~2 _  q
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    . h( n; Y7 n! V- w) G4 c
  36.       textData = currentLine;              // 将textData指向currentLine- o- l. A/ ~& Y3 }: e
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    0 G9 M3 h# F9 Z  U  b# R. u
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表' T/ H8 b9 k& V& s) |2 o# C# Y
  39. % d( m5 ?7 O* _/ t* G7 }  ]
  40.       if (lineIndex < numLines)
    3 L( N9 I& b5 V
  41.         lineOffset += 4;                   // 更新lineOffset9 L5 _7 t5 t6 w- @
  42.       ++lineIndex;                         // 递增行索引$ ]. A" b' D: M
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据# P9 g: i2 |+ ]6 ~) Y1 e
  44.     }& @4 }6 L1 `* k
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    / V4 t9 C! ]/ r3 U4 B# q+ f
  46.     glPopAttrib();                          // 恢复OpenGL属性状态, Z6 |/ A0 l. K" W+ c' A* A
  47.   }
    9 s/ Q3 B7 u( K' r- S% G2 g' \
  48. }
    5 g; p7 A" d# A4 Q* R
复制代码
& o7 W$ K- g4 K! r( M6 |4 }% W
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
0 ^/ }7 [/ p+ \" p
2 R# L" h9 T+ K6 N2 _8 C3 yint xOffset,      字幕的x坐标) s/ b$ H! t) E: d. g: R( h1 d
GLint yOffset,    字幕的y坐标
5 t: u, @7 B/ m- x; Iint numLines,     字幕的行数(较长的字幕为2,一般为1): G7 e! K! K' G+ q
int lineOffset,   这个需要再研究
1 L% F/ n: o1 Y  h! ?int lineHeight,   字体高度(或行高)" O+ K0 U0 j' [$ n& `1 h" o
GLuint displayListBase, 这个字体对应的base值
# N& S; T3 d% R% W8 Rchar *text, ...         字符串
; f/ v8 B! @$ n# s) Y" f; S
/ P6 {  {5 V- L+ _9 g+ Q. Q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

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

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