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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
  |2 l8 U1 k3 k, P( k8 }. V
6 U3 y8 Z* J7 Y; R这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎8 ?0 X- M2 x* S3 X# C) O0 w
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。9 x4 R* S+ d  k' X
https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
4 d) X' J) N7 ~$ B1 s第1处( H5 }- a8 Y1 v$ N& l$ ^. A6 i
  1. void sub_451474(char *a1, ...). Q7 i5 w; \& Z) x6 l* t
  2. {# i. ?. I6 ^8 r. V6 s. C9 O
  3.   GLsizei v1; // eax
    6 f& X+ [5 Y2 l" f0 [! E5 R6 O& {
  4.   char lists; // [esp+4h] [ebp-800h], E) F% I- Q- I% a; O. M* w
  5.   va_list va; // [esp+810h] [ebp+Ch]
    ; S- o  E: K& ^

  6. % B$ u' K& S, d& ]" b& f( i# m0 w7 L
  7.   va_start(va, a1);; ~) F) f0 m/ ]7 I3 p
  8.   if ( a1 )7 @8 L9 \' ]$ E* n
  9.   {# J2 c# O2 M3 z- \' l- v
  10.     vsprintf(&lists, a1, va);$ I3 Q* w! W$ P* h" e9 r' w$ W
  11.     glPushAttrib(0x20000u);1 \- O0 W5 C( i# ^% s6 v
  12.     glListBase(base);$ Y5 K" z$ X( N: T. d0 A1 P
  13.     v1 = strlen(&lists);
    $ @. ^" j; M# |/ g% {: H3 Z$ ]
  14.     glCallLists(v1, 0x1401u, &lists);
    6 Q) y. q' p5 z$ H6 I# ~
  15.     glPopAttrib();
    ) H0 z. C2 V- I. k
  16.   }
    + d, }4 z7 R: Z. ]
  17. }
复制代码

0 _  {# l# F& `* I- W( i4 i  u( x
! T3 B& _* H; y2 r4 T2 ^% o3 I
第2处
" {+ o! {1 y, J7 ]2 }  n0 d# d) L
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)! z# W8 V& c, U, Z
  2. {1 a1 H/ ?6 w7 M0 g, _
  3.   int v4; // eax
    . u" C. V: O5 X* g9 ?" f
  4.   GLsizei v5; // eax1 ^/ G4 w; I/ R, `% f
  5.   char lists; // [esp+4h] [ebp-800h]* k5 \7 z/ e' N4 t. \
  6.   va_list va; // [esp+81Ch] [ebp+18h]# l2 K5 Q7 ~- I3 _% Y
  7. 4 A* E' h5 c% ~' `8 Q
  8.   va_start(va, a4);- y7 L; @+ J; @6 j5 E* J* N7 z
  9.   if ( a4 )) _/ Z+ R* N3 u! ^# H" M
  10.   {* Q5 q8 v) `9 s# E
  11.     sub_44F8A0(a3);
    5 N2 B! F+ W" N* R7 `
  12.     v4 = sub_40BB44();
    8 `! `' q/ i+ P, r+ d: y
  13.     glRasterPos2i(x, v4 - a2);
      |* P0 j# e: q& c# C0 F
  14.     vsprintf(&lists, a4, va);
    + F6 M5 q% r" ]) L8 k: P* W
  15.     glPushAttrib(0x20000u);( X3 }+ z- C$ _
  16.     glListBase(base);
    8 m8 `* X( T% l; ?. H+ c% B8 p
  17.     v5 = strlen(&lists);
    . v5 W5 W1 c# k. y0 n- G
  18.     glCallLists(v5, 0x1401u, &lists);6 x5 a& {6 T# y7 \
  19.     glPopAttrib();# ^- Q, N% M; }" N) Z: T/ q, Y
  20.   }2 b, D1 f4 l# M! B9 h/ d/ h' o
  21. }
复制代码
0 _# S' K' z6 C& ?
2 _' E. p# J' {% }- h
. v5 s$ q! z) y; ]1 ~4 B0 j: Q
第3处# D/ P) q1 d. V' `# c! v2 P
  1. $ B$ E: R, {, h8 j) e1 k
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)% t- r$ G7 f5 G# m2 W
  3. {
    : R% j+ v; a& v. K
  4.   GLvoid *v7; // ST08_4. t' V* c# K) q! z* L. M5 t4 T% {
  5.   GLsizei v8; // eax
    * q% H- E3 J4 g& v; m! x
  6.   int v9; // [esp+0h] [ebp-1018h]& B* N0 i; l9 f
  7.   char v10; // [esp+8h] [ebp-1010h]' o9 x- w, y. H% L
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    , M* C& u6 O6 S5 @0 |, v" E
  9.   char v12[5]; // [esp+1013h] [ebp-5h]
    " x0 O9 H$ [8 {* w; e' D
  10.   va_list va; // [esp+103Ch] [ebp+24h]. w5 K. }3 ~, x' N4 D& X! T
  11. . {, _/ D+ ~4 U% O9 p
  12.   va_start(va, a7);9 Y/ C0 S* ?- j# O4 u* H- W  g
  13.   v9 = 1;# q' y4 X' V1 k7 W9 Z# \0 Q4 G& p
  14.   if ( a7 )
    1 l, i. X$ R) r
  15.   {5 |, ^6 \( Q2 |- s
  16.     vsprintf(&v10, a7, va);! D) A& v+ c. q0 F
  17.     glPushAttrib(0x20000u);2 |2 `. j' P9 t0 w0 C' D- L9 c$ z
  18.     glListBase(base);
    6 B3 ?* _& g) Y* [* R
  19.     lists = &v10;5 \$ R/ e$ p3 x, S, D0 P1 u) Y
  20.     do! b# k3 p6 K; @( P! T) C
  21.     {
    - _) _1 V: r% m; @9 k4 n
  22.       *(_DWORD *)&v12[1] = lists;
    " V6 `2 F* w' S6 n# }3 W
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )* i- i/ _/ [: `
  24.         ++*(_DWORD *)&v12[1];
      ?: t* D! L4 p+ ^6 `" F8 \
  25.       v12[0] = **(_BYTE **)&v12[1];+ U5 ~+ d/ R0 S2 {4 q! V8 L
  26.       **(_BYTE **)&v12[1] = 0;5 v) a+ H" j# q
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )& |7 G( u4 U5 Y) f
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;; l- {; C3 H) b- d  v8 s
  29.       y -= a5;
    ( ^* ^  b: J) N+ E! F# w' o6 U) W
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);* w5 \$ h$ v4 P( i' f
  31.       v7 = lists;# |$ z' A6 L$ \) n1 [8 ]/ N* ?: N7 ^
  32.       v8 = strlen((const char *)lists);1 J8 y' B; n; p" G
  33.       glCallLists(v8, 0x1401u, v7);4 m( ?- T8 W4 _7 ~9 ]+ b( K
  34.       if ( v9 < a3 )
    ! {$ a' J! }0 D* {
  35.         a4 += 4;" g1 w2 y6 ]4 ^+ ]
  36.       ++v9;
    7 b' v  s1 }, R
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
    * G( E- [! W1 \: r$ i, l, w
  38.     }
    8 _/ J# J8 Y7 ~; Q/ A
  39.     while ( v12[0] );
    + H" G; @. h# \9 _+ C5 Q' ~( H
  40.     glPopAttrib();  m+ |/ H- [7 j0 X
  41.   }
    ! v, s6 z8 F* Y  a3 V
  42. }
    & [* g. O3 o/ d. [
复制代码
( e  W4 @) m6 Q3 y) T8 y  ^
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_4518105 n. V% _" d9 w' J& U. d% p
' T. ~, k" Z: ?2 x* Z
  1. .text:004512B1 52                                         push    edx             ; char *& S7 f2 N0 I1 \9 Y/ M6 {
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    : ?7 x* E; y; c9 M5 e
  3. .text:004512B5 50                                         push    eax             ; base
    5 i' z) T+ T0 L" q/ m
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    5 D! a% Z1 K. J% f4 Y
  5. .text:004512B9 51                                         push    ecx             ; int2 K9 b  Z; n& S: I
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]
    " L$ G! d, a$ @, x
  7. .text:004512BD 52                                         push    edx             ; int
    + R3 D2 N7 q& G& Y( L  d- |
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    , E, k3 b5 [  q% d8 Z6 }; k, c/ p; {
  9. .text:004512C1 50                                         push    eax             ; int
    7 ^. R$ s! h" t7 y! u5 I# A
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]: m5 Z" t! P" ?. G1 K; Z; P
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]9 A7 P; P; u6 L1 ~7 E7 y
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    + J& R4 V$ q3 f+ b8 K
  13. .text:004512CB 51                                         push    ecx             ; y! A: s# Y/ k  z% E0 x) X- D
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]% w' C. D  D$ i3 K2 M$ }1 x' ^5 r6 y
  15. .text:004512CF 52                                         push    edx             ; int/ h$ e! V& K( U$ B: [/ r( u
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
/ P: l7 P* E& A
chatGPT整理过之后,如下
( J% a: C' l. B- o: k2 V
" R: G* J6 k/ }: o1 }8 w% U0 U, M& \
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    . ~/ i5 M9 k# u: c
  2. {
    1 e3 a, r  J$ `* I/ O
  3.   GLvoid *textData;         // 存储字符数据的指针) G8 Z! s6 f; |/ Q4 ?7 Z
  4.   GLsizei textLength;       // 字符数据的长度, ~+ e8 d& g2 N
  5.   int lineIndex;            // 行索引
    % }2 @# Z; h% x( `. A6 R
  6.   char formattedText[5];    // 存储格式化后的字符数据* q8 L% i6 M1 `0 E; A
  7.   GLvoid *currentLine;      // 当前行的字符数据指针; j2 |) L* j6 Z8 M& W
  8.   char buffer[5];           // 字符数据缓冲区+ s, V- `3 M, Q9 N
  9.   va_list args;             // 变长参数列表
    - K5 @3 x" w& R+ B2 B* _) [

  10. 6 g- t1 }; ]4 f0 o5 b
  11.   va_start(args, text);     // 初始化变长参数列表
      e3 R' |! y9 Y7 Z
  12.   lineIndex = 1;            // 初始化行索引为1
    0 v3 q5 x  g) t
  13.   i$ X+ [) Y. v
  14.   if (text)                 // 如果文本不为空
    + M- k  ^7 I4 r. m; M# F+ n* Q
  15.   {
    8 U6 h( U1 }6 _- \) s1 Q( G
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中* f8 ~+ R7 Y7 ~
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态- ~! A% Q! G' ?) R. o3 s- E
  18.     glListBase(displayListBase);          // 设置显示列表的基础值8 H4 y7 E( S& X" L$ e* T: P' f: D, {
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置- f, F" d% I  B
  20. ( i  O4 U3 u7 e$ C" H, H# [
  21.     do
    . F3 L$ g: r; v7 Y: ~
  22.     {
    4 O! y* @( B. a, U9 ?' O7 [1 s5 b
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素$ Z7 `1 O0 a, w5 \4 k9 m6 H) ]
  24. 8 Z' K# I( v7 h( i
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
    * I; P& K% M/ n% {( |3 V
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    " a; r' r# b- R6 y/ d, \  k2 }
  27. 2 N: t4 i; F; R
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    8 |# t0 D/ _9 f4 u; `1 y! |; m
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符6 @4 K! C. F' ^, r8 g( {. v( a% Z1 G
  30. 2 x. ?, D* X4 D
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)* I9 A- x- a" z% F
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符" U* W$ U8 l- b3 G

  33. : _2 B2 N: ~- P1 W9 I
  34.       yOffset -= lineHeight;                // 更新y坐标, P8 B  @' S# ?' M& E" v
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    : ~( z1 t$ ^, a7 M% ?
  36.       textData = currentLine;              // 将textData指向currentLine) c; N- K( g( p# t
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    6 T  }( F* P* o! V4 Q
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表3 r. }) G7 s' i: h, g

  39. ' U; j, \; y: d; o! n, B
  40.       if (lineIndex < numLines)
    3 T) Y' Z9 N& U% g
  41.         lineOffset += 4;                   // 更新lineOffset& B  z8 T7 o# f7 q
  42.       ++lineIndex;                         // 递增行索引) m( ]1 W) f* l+ i# e4 }
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据! ~) X; |2 ]" t) }4 N% v
  44.     }
    / p( H3 `! g8 T4 h2 L! S: ~; T; \
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环7 q* i, M5 D' m' }4 _
  46.     glPopAttrib();                          // 恢复OpenGL属性状态( e6 }- V9 O5 ^( v% ?
  47.   }
    7 \4 M- I" H" a
  48. }! ^# U9 q% E1 D7 l
复制代码

+ f9 F( v. z) G6 J' m% [# L含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前3 H% H3 L' ?5 q

9 y( r- |4 S! r& L  _5 }0 Dint xOffset,      字幕的x坐标
" w$ \( d2 y& L- q8 i6 lGLint yOffset,    字幕的y坐标8 o% g2 L- H- q6 y( ^
int numLines,     字幕的行数(较长的字幕为2,一般为1)
$ ]6 X  {; o' J/ x" zint lineOffset,   这个需要再研究9 c5 I7 w; r! X
int lineHeight,   字体高度(或行高)
5 T# s, o7 P9 O: N( h5 v$ tGLuint displayListBase, 这个字体对应的base值( g: q6 O7 K9 U1 |7 X: j* q; Y) x
char *text, ...         字符串) ^! |) l# \- J
6 C8 k* l7 G: d$ q
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
5 I2 ^4 n! D# \$ N5 z" U. q
回复 支持 反对

使用道具 举报

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

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