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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
9 U, j" v7 ]7 S3 i0 N
4 \; u0 [, F: s( p6 _这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
: a( j# \( D: f- q$ K  H因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
: U; f- t* G9 s1 ~. `https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
$ i8 H7 X. u* H2 _7 g: ~第1处; R8 I. S! E' S$ K. R8 G# K
  1. void sub_451474(char *a1, ...)1 b: {  [3 e& N7 T% i* r
  2. {4 t) F( ^) D$ W6 D9 x% q1 c  D
  3.   GLsizei v1; // eax
    9 G+ V+ r8 ]/ A$ ]; g( a" y' e$ n
  4.   char lists; // [esp+4h] [ebp-800h]
    2 J" l9 Q8 A8 u* k$ |$ s$ ]
  5.   va_list va; // [esp+810h] [ebp+Ch]+ M2 `: A* y& Z
  6. # b5 ~$ W" p0 `
  7.   va_start(va, a1);
    ' }8 z* h& `( R3 T& v8 Y+ }6 P7 q
  8.   if ( a1 )
    4 G3 l: ~: _0 p$ }
  9.   {% M: o. a) t6 Q: S# I
  10.     vsprintf(&lists, a1, va);
    - B' j: U: |* c% K2 S9 c# W, T
  11.     glPushAttrib(0x20000u);
    / o# T2 a1 W& k* e. k+ L: r
  12.     glListBase(base);
    4 a6 M7 M) [) d6 r8 b/ V
  13.     v1 = strlen(&lists);. H% n. A! A3 O- a  F
  14.     glCallLists(v1, 0x1401u, &lists);; j8 Z( n. [- {( I5 }
  15.     glPopAttrib();
    2 q! o8 [$ M) z1 p$ b( g
  16.   }) U: k! ]2 ~; q+ v( I1 z) V
  17. }
复制代码

8 M0 |/ E  W; I: E2 ^) x3 u! a& y: G0 l. a- W% C/ M

8 m' Y9 K: Q% V' _3 |第2处
  R2 z8 R( w2 B
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)) V5 t3 y$ p2 X' h7 V  s
  2. {' V) \4 T: W% c: }5 \4 \+ U
  3.   int v4; // eax  @! _$ v8 l4 p0 m" l
  4.   GLsizei v5; // eax
    ; y9 E+ @; p$ r+ d" S& A
  5.   char lists; // [esp+4h] [ebp-800h]
    ! X- B: U4 k4 w' l  m
  6.   va_list va; // [esp+81Ch] [ebp+18h]
    6 _2 u1 b# r) u  i" F* g: M

  7. 7 R6 Y9 K5 v( v7 P# L+ O9 \( t
  8.   va_start(va, a4);0 c( v! G2 p' u( ]8 n& W" H
  9.   if ( a4 )2 `: X; t: b5 N8 x: z7 l% [
  10.   {
    4 @  i: E! w+ C, V
  11.     sub_44F8A0(a3);7 H* h1 Q! C& ~+ p7 J7 Z. s
  12.     v4 = sub_40BB44();" x3 {+ j, a! M/ P5 @" Z$ o
  13.     glRasterPos2i(x, v4 - a2);
    : F- }9 [3 F7 h2 a9 K
  14.     vsprintf(&lists, a4, va);
    2 W. j# p- g7 v( w4 k
  15.     glPushAttrib(0x20000u);
    3 d; ~8 g( N- N4 g* n9 l* ?2 T
  16.     glListBase(base);
    5 M* i( v9 E4 u
  17.     v5 = strlen(&lists);4 E% |" p# [  W; v
  18.     glCallLists(v5, 0x1401u, &lists);1 \% i/ z# B7 W, n  x
  19.     glPopAttrib();" Q' Q# B3 |" Z$ ^
  20.   }
    0 T* w3 `8 K7 v1 T" M1 p  J: c
  21. }
复制代码

2 v( x" {# f" L- @( _2 Q/ ^
: H! M) G' [2 V7 \" g/ a7 D, W+ H" _6 q+ f' \
第3处
; v2 M$ J) o# q" |+ E
  1. 8 C6 U/ V: u4 C0 Q/ Y; u
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)' O5 G0 D  N3 A6 E
  3. {) p% ]# \4 d1 n8 h" m- o
  4.   GLvoid *v7; // ST08_4( Y) _- p* R  n: J8 V
  5.   GLsizei v8; // eax
    ! t& C3 U* |( Q6 B+ k
  6.   int v9; // [esp+0h] [ebp-1018h]8 H# R' {% X% K7 |# Y- l
  7.   char v10; // [esp+8h] [ebp-1010h]
    + c  D& y, ^& }7 v& E& i, Q
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    % T8 E3 m* ]- u" |/ [
  9.   char v12[5]; // [esp+1013h] [ebp-5h]
    4 c3 a/ a0 K9 i' c. ^
  10.   va_list va; // [esp+103Ch] [ebp+24h]5 f4 m/ q' m! G0 I

  11. 6 A& y6 y+ a% _# Q! c
  12.   va_start(va, a7);
    : z2 J3 Z5 T, q' C
  13.   v9 = 1;- ^) u/ ~) B" r" z$ H+ z& L3 I
  14.   if ( a7 )
    8 {: T" l8 q# Y+ G3 V
  15.   {
    ) I1 T' j3 C/ p) x! T
  16.     vsprintf(&v10, a7, va);" a$ V$ z- ~6 M% R4 q  S" J& P
  17.     glPushAttrib(0x20000u);
    1 K) Y' r0 m2 |5 @" x
  18.     glListBase(base);5 D$ j' V6 H- A0 R( z
  19.     lists = &v10;9 R! e6 _) \6 A: _# C2 E4 S1 F
  20.     do
    / ]; |) \7 R3 V% i+ S
  21.     {8 T4 f6 O$ G& I# P; ?) Q3 M1 y
  22.       *(_DWORD *)&v12[1] = lists;
    9 }% K; [5 K% R. S+ e) W4 V0 f
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 ). `* v3 i; }; m6 f# _7 T8 v+ R2 m
  24.         ++*(_DWORD *)&v12[1];, B% E8 d5 D3 ~: ]/ R
  25.       v12[0] = **(_BYTE **)&v12[1];1 m5 {5 t" `: o* ]" [
  26.       **(_BYTE **)&v12[1] = 0;
    5 z1 y- V$ q4 Y6 @- ]
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )" ^9 ]5 W* [# B2 o' c. G% G' [3 F- R
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;, O0 ?2 c7 B" o- N
  29.       y -= a5;- o* G( n/ a0 d6 F
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    . ?  G: k, n& f7 {5 H& C. |& t
  31.       v7 = lists;
    4 {+ H3 t0 i5 U4 x
  32.       v8 = strlen((const char *)lists);
    , ^( h7 Z+ z/ o! l
  33.       glCallLists(v8, 0x1401u, v7);
    6 O: e- T. `# W: N
  34.       if ( v9 < a3 )
    # \" |6 V% f7 x. O$ O
  35.         a4 += 4;
    5 s" r- E. R: ^% K0 i4 e
  36.       ++v9;6 J, V/ n! I  e
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);& w& D$ a" L, |9 Z0 q& j9 u' s
  38.     }
    + ?+ a! [( g0 c7 N4 _! J
  39.     while ( v12[0] );" w8 v/ R5 W+ x, w
  40.     glPopAttrib();  `4 f$ |% y0 \9 M! u
  41.   }0 f1 o6 p0 u, W0 ]
  42. }
    0 y% P+ v$ m/ `/ Z% m2 n
复制代码
/ y0 m  Z2 c- I/ T9 p# I
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810- S& p- @; N. p( X: z+ @4 ~9 f/ G: S
6 F% E6 V. p& {8 D4 R1 I& D# U2 X/ G: J
  1. .text:004512B1 52                                         push    edx             ; char *; p2 _1 N; ~7 J7 p0 }7 z
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base], R5 o, X5 y* u
  3. .text:004512B5 50                                         push    eax             ; base
    " A/ Y: ^' w- f! u; C. N8 _1 Z7 L
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]( w3 h4 H( R# X8 M
  5. .text:004512B9 51                                         push    ecx             ; int
    - {5 t) z$ Y- ~; z/ C
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]# N8 ~# u5 j' Y' _' y' q
  7. .text:004512BD 52                                         push    edx             ; int7 \" D( c4 v9 u) t
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    & S! [7 m  P; b
  9. .text:004512C1 50                                         push    eax             ; int
    * `6 _9 ?% K, _& X- Y' L, R
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]" Y7 M3 W: X; M4 t5 ^( D! v; `
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    - I* P. ~5 ]1 q
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]" Q1 ~, ]/ F2 k! b6 t
  13. .text:004512CB 51                                         push    ecx             ; y
    ; R& `) T2 S0 _
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    - o% Q6 ]# s( L; s
  15. .text:004512CF 52                                         push    edx             ; int* ?- {/ S9 q/ W; n
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
, p, \9 A1 x5 q+ W) _% X( H! d9 V& J
chatGPT整理过之后,如下4 X4 m3 F+ c0 |7 q- U, s& x
% d  E( ^/ [0 _5 \
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)! V5 a3 W4 h$ g1 p/ K
  2. {
    ( O8 N  _3 v$ H
  3.   GLvoid *textData;         // 存储字符数据的指针7 g6 ~6 d+ @. m7 n+ W
  4.   GLsizei textLength;       // 字符数据的长度
    1 I# W) k' N! H6 J2 L2 J
  5.   int lineIndex;            // 行索引" p% [$ Q$ i; n; i
  6.   char formattedText[5];    // 存储格式化后的字符数据& q% y7 P' z  A' K) Q! C; I
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    9 |% g2 p- b2 @  v& p
  8.   char buffer[5];           // 字符数据缓冲区
    5 \8 z  [1 i, B( V  E+ A2 T* E$ l
  9.   va_list args;             // 变长参数列表
    0 G' s4 q3 N& {/ C" d, `% f$ t

  10. 8 T- z# \0 h; q( W* A4 K1 e* Z# l
  11.   va_start(args, text);     // 初始化变长参数列表
    ! R. y2 n/ F1 u. f
  12.   lineIndex = 1;            // 初始化行索引为17 t& {: a  J/ i8 ]

  13. % _- c7 p% r# T6 H2 K  k
  14.   if (text)                 // 如果文本不为空
    8 @9 s% h6 w2 Q; H  f6 p! f% t
  15.   {
    # {2 M" _" J( X
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中
    ( k) T9 K1 ]+ }5 W2 l2 C4 l+ I
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态7 C1 i) S7 U! v6 R( L
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    ' `: k* D2 f& M; \* K5 F2 u
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
    ! }" E+ U0 G; U( L9 |1 Z# r
  20. % O! @0 r. R+ x, N
  21.     do. L  p$ @2 U- b# c9 K9 f- a
  22.     {
    2 w" u, [1 m# b& r& D; k
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素# o% M' J# Y3 b/ g- G) `' t+ z& p

  24. ' y. ]/ y+ v7 J1 h) i
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束8 U# A* a  d0 n  Z, o
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素0 j; E/ M7 |. c5 y* j0 b
  27. ; U0 T! y; Y$ ?, T; K( [  E
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素5 Y& q2 M0 u/ _$ k$ O# z
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符
    , k0 ]' n5 W; L  A; ?6 A
  30. # l" o- L6 A! y6 L& G9 R
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    2 R' K# V3 [$ {, b  U2 I7 c
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    * l6 v. I) T7 q1 d

  33. ( Y# p. e/ z( _3 ~5 i
  34.       yOffset -= lineHeight;                // 更新y坐标6 ^) E0 D- W, l1 s8 a8 a  I
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置( u4 O, W7 U  q- `9 w& v) n
  36.       textData = currentLine;              // 将textData指向currentLine
    - \: [* C* [8 i( d) G/ e) S
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    * Y8 T" P, U1 R5 `* y
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表, f& Z; J9 M4 q# i; Z- j$ O' E1 v8 O! N
  39. 2 I7 x( @  s, q) k9 ]
  40.       if (lineIndex < numLines)& `; B1 T$ Y3 {" h4 m9 I
  41.         lineOffset += 4;                   // 更新lineOffset
      r+ ~! t& k$ y  o
  42.       ++lineIndex;                         // 递增行索引, q/ }8 h  m7 ?# u& I% |7 A
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    + G) R& ~/ e! y3 H# \+ U
  44.     }* g) n! ^1 b; Q* n
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环! N; g/ S" ^# I6 Y) g
  46.     glPopAttrib();                          // 恢复OpenGL属性状态* b0 s! D' D) t/ c: M* ]' K
  47.   }
    9 t2 _% Z, E- h! k7 K3 [; O7 a
  48. }, p( z; y5 S8 u3 N& b. h9 G
复制代码
; y- N) y$ C/ K+ D# k
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前1 Y! W: E7 |/ A: k) L! d3 _, ^

4 m4 a% y1 W7 g. y% P+ a3 mint xOffset,      字幕的x坐标4 ~  ~; c* L2 ~( Z3 r- d: y+ W
GLint yOffset,    字幕的y坐标
  _$ T3 _6 K* c% N' O6 B$ sint numLines,     字幕的行数(较长的字幕为2,一般为1)
6 ]" i6 Q1 i* W% b7 v  Gint lineOffset,   这个需要再研究
( {( _& i% R2 W* b2 O0 Q/ ^) t; pint lineHeight,   字体高度(或行高)& x% B+ W0 ~1 c' N
GLuint displayListBase, 这个字体对应的base值& I! ^0 {9 K8 l2 S' `
char *text, ...         字符串0 D6 [0 y0 M9 w5 C. o
; M& ~, W) G1 O& `! g
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
; Y' {% E& l1 `. a2 |8 }
回复 支持 反对

使用道具 举报

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

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