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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
% l0 k% d- H5 M0 P; l
9 s; c4 h% q- k; u6 Y  i这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
; m' u: e7 N/ S5 I/ Q因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
3 ^6 t0 o+ m0 ?https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081: H3 G* n  g' u/ Y, ?9 `
第1处9 V3 F( A9 m5 I2 i) F4 \
  1. void sub_451474(char *a1, ...)" h9 u( u7 }) U! h; J2 k3 j& F
  2. {2 u  j) o6 L2 n; h/ `. g9 G
  3.   GLsizei v1; // eax) q6 U) |# ^6 p& L! w$ n
  4.   char lists; // [esp+4h] [ebp-800h]
    $ B: Y8 m! Y& m5 Y2 b! i
  5.   va_list va; // [esp+810h] [ebp+Ch]+ a+ o$ w+ D6 m+ e1 ]
  6. " u% t- S; e4 J& B5 D/ g
  7.   va_start(va, a1);- b7 f5 \0 H4 V& t( L
  8.   if ( a1 )
    0 Q7 y2 \* w# x- O2 w4 u
  9.   {
    9 Q3 N" g4 |9 \2 ~+ Y8 }: E, @
  10.     vsprintf(&lists, a1, va);  d# t9 e' C  J
  11.     glPushAttrib(0x20000u);
    ' u! D- z/ f4 @; w; f# p+ O% F# g
  12.     glListBase(base);
      l, U* t: V9 P% ^* n1 J$ W
  13.     v1 = strlen(&lists);7 T- C5 y' Q3 F# r
  14.     glCallLists(v1, 0x1401u, &lists);
    9 b" Q& Q3 B2 ]; k2 j
  15.     glPopAttrib();
    : ?4 w! ?. x. @" b  g
  16.   }4 F. r* q1 Y! F: j+ d3 E
  17. }
复制代码
: Z$ |  e1 y- R9 P6 e- }3 I
- T2 n! P0 n; g3 d0 U2 A

! S9 \/ c7 K+ V* O; T第2处
* w, H8 q2 v, Y* ]8 R# \7 E
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    - d) _$ A$ M  [+ |- _2 Q) @
  2. {# c' E* \) T6 {) Z7 A! U# u$ G
  3.   int v4; // eax' ?; U& c0 G  q
  4.   GLsizei v5; // eax$ {! Y: h" }" y: s$ g
  5.   char lists; // [esp+4h] [ebp-800h]
    8 C# g) f1 h1 }' N! G0 p4 s
  6.   va_list va; // [esp+81Ch] [ebp+18h]
    1 ?- C5 S2 c! Q% k( l. ?
  7. % ^. a1 {8 o& b. P
  8.   va_start(va, a4);
    : z1 ]; c, ^- m2 Z3 y/ J0 N
  9.   if ( a4 )
    - B+ Q1 h1 j& H4 L, e
  10.   {
    * G! `/ \6 {0 m4 c; ~! j7 |
  11.     sub_44F8A0(a3);/ C/ |" o& j0 V1 I
  12.     v4 = sub_40BB44();8 u) `3 x  [5 `2 q( z, h" `1 t; |8 \
  13.     glRasterPos2i(x, v4 - a2);
    $ \, u( C% @4 T4 a
  14.     vsprintf(&lists, a4, va);  b/ ?: X' F2 A% H0 k& p
  15.     glPushAttrib(0x20000u);
    : L& y% X1 g3 m, O9 p. _% B# l5 A
  16.     glListBase(base);
    . M+ ]5 r# n  A; v
  17.     v5 = strlen(&lists);- C* k! Z" `/ D+ w4 R+ W
  18.     glCallLists(v5, 0x1401u, &lists);! L* v( ^8 O7 o- K8 W8 I
  19.     glPopAttrib();
    ( G( b  N/ p( S& g! R6 S6 ?# `
  20.   }. A& a9 u/ h" }1 B! Z
  21. }
复制代码

3 Q$ T3 N$ v. r* V* z
; P* B. a' v/ q3 x9 i, R8 y: ^, C: K
第3处
: ~& w  o9 i% A; h/ C
  1. 2 j* R+ G4 L+ h3 Y
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
    9 g: D* C0 c3 h# t* {% t! Z3 d
  3. {$ p4 z  @. C% ^& g/ h" X
  4.   GLvoid *v7; // ST08_4
    6 T! Y: N+ ]( q* A) [
  5.   GLsizei v8; // eax
    " A2 t* e; B- g6 e2 E6 n; h
  6.   int v9; // [esp+0h] [ebp-1018h]+ _" U; a% o' n7 [* O; ]: U" ~
  7.   char v10; // [esp+8h] [ebp-1010h]: [. s0 u2 s& x* D
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch], J5 p! D5 }/ v4 Y6 H) g
  9.   char v12[5]; // [esp+1013h] [ebp-5h]8 z' Y: y, m, t
  10.   va_list va; // [esp+103Ch] [ebp+24h]
    ' y/ M7 s( s$ o: J
  11. # W* H$ s( P% ?$ w: p
  12.   va_start(va, a7);5 o0 {  `5 \* S5 y2 h, X* f9 ]( E
  13.   v9 = 1;' ~. M( s: G5 V5 c- y6 n6 i: O% \
  14.   if ( a7 )' y; s+ p/ a8 g3 N6 o7 W& J/ M& [
  15.   {
    ' p3 {  l( D# d  g* Y: B
  16.     vsprintf(&v10, a7, va);9 j% @- ]/ R3 ?3 M  X3 E
  17.     glPushAttrib(0x20000u);
    8 \) s8 ?4 S2 G" u: V) [
  18.     glListBase(base);
    6 w! G/ ~, u5 B6 x$ E( A7 q
  19.     lists = &v10;
    3 S0 B$ f% }; C$ V- D1 |$ u
  20.     do
    / e; y  x. v1 a8 O# o1 G
  21.     {0 k" i" s* `" b' k* ~4 G
  22.       *(_DWORD *)&v12[1] = lists;: m0 i7 E* M9 I# k, H1 R
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )
    ' {6 W- Z3 u" c/ [  S/ x: ~
  24.         ++*(_DWORD *)&v12[1];
    0 G' b9 R/ o1 q; {- g& G/ E9 |
  25.       v12[0] = **(_BYTE **)&v12[1];
    2 B. p- e! `/ p! G; V: b8 A& q
  26.       **(_BYTE **)&v12[1] = 0;5 a; M! _: ]+ ^( @, j' c' K
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    7 u4 W7 B; x1 U; f  f, ]6 U) |4 y
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;% p3 a4 m% B  A; Z
  29.       y -= a5;
    / H( L% T7 n, n  k0 p7 ?# g
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    * k& Y3 ~+ [  r- j. P
  31.       v7 = lists;
    $ t  J- |; J& M" X$ P  b) b4 ]
  32.       v8 = strlen((const char *)lists);
    ; }) n! Q' d5 }, `7 n
  33.       glCallLists(v8, 0x1401u, v7);
    : s7 e  Y" z0 {2 O
  34.       if ( v9 < a3 )5 K; E3 [  R  P$ d
  35.         a4 += 4;
    ; |7 F9 H, T6 [
  36.       ++v9;
    " D1 ]+ @, i* |0 L
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
    4 n' H- O% \" O! i5 V" D$ k+ s+ J
  38.     }2 }' v# z. K7 {. Y  M. s: Z8 c: t
  39.     while ( v12[0] );
    / y) H$ K  ~9 R* C; b' v
  40.     glPopAttrib();
    % s5 l7 z1 F/ Z! _! r0 Q0 o- A' J
  41.   }' j$ m( ~5 u9 J, O- O
  42. }' c3 o+ a& i, l0 l- F5 l0 G
复制代码

  ~: T6 B, [- D! l# ^6 r调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
; b! b1 S# i% d( o2 S1 Z: A2 F$ Y' |) j: d8 v5 A
  1. .text:004512B1 52                                         push    edx             ; char *4 u5 j$ x  K" Q5 b" r" x0 [$ i
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    $ u$ `8 c2 \4 y1 ^# @4 K) n3 c( ]
  3. .text:004512B5 50                                         push    eax             ; base
    ! W  i8 S8 o# E2 h7 j( v
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]" R8 x- x% A/ r- a. M% ~: [
  5. .text:004512B9 51                                         push    ecx             ; int
    $ w9 D! v1 r& v# [, t  u' e
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]8 O3 b! I/ Y8 G3 H8 ]
  7. .text:004512BD 52                                         push    edx             ; int
    4 H5 M4 t" \- \/ B, {5 ]; K" y
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    ' X$ |- D2 V, c9 z# v" V+ t2 O
  9. .text:004512C1 50                                         push    eax             ; int
    0 p; ]$ y. @* ]' p
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    # A7 Q% f( @9 g8 j
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    & [6 _. y* f4 q
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]! b+ ^! Y6 E' j' ~6 i
  13. .text:004512CB 51                                         push    ecx             ; y
    + @  G: T4 [; t9 z3 ?
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    " e) q  @- K2 f' r3 N6 M8 ?
  15. .text:004512CF 52                                         push    edx             ; int
    0 V# e6 E2 H, Q6 L* D
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
1 J7 M) k* e; s4 O3 \. Y1 W+ K
chatGPT整理过之后,如下; m. k; q0 C' {: ?7 l

9 C' C, q5 j- x* T! v7 Z! h# q* P" k
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)1 h% C: ?4 m) }; r
  2. {
    6 K+ m; r$ \4 a/ c& i6 k
  3.   GLvoid *textData;         // 存储字符数据的指针
    . L& ^- b4 B6 }9 L
  4.   GLsizei textLength;       // 字符数据的长度. B2 Q. ^% E5 ~  m. f3 R
  5.   int lineIndex;            // 行索引* G( `) z0 l+ [9 T( p
  6.   char formattedText[5];    // 存储格式化后的字符数据, q* Y. Q3 I: I/ G6 v
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    0 c$ `7 I2 P8 A- k9 T# e) d: E# Z
  8.   char buffer[5];           // 字符数据缓冲区* c- h# K: g. Y8 Y! g% q
  9.   va_list args;             // 变长参数列表
    : i) g9 W* b, h1 n4 Z
  10. 3 _- Q; E& m+ z) j
  11.   va_start(args, text);     // 初始化变长参数列表2 h* B5 }2 ]+ w
  12.   lineIndex = 1;            // 初始化行索引为13 n0 m. j5 c/ o
  13. 6 F" d8 l4 L* R. L% ~
  14.   if (text)                 // 如果文本不为空
    1 y3 K( U2 Q2 F# w$ l
  15.   {' N6 N3 V3 x) K: q
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中+ f" c0 K# Y0 d9 f  p; @
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态$ [1 F' A7 l5 V1 `! V4 ?5 R! Z. G
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    " z3 \2 j. f9 k
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置3 A0 a& z# B; D) w1 D7 ~' v
  20. . t" I  ]. `- u1 T( [
  21.     do
    8 [* j4 w6 a% k' [2 w/ E' n
  22.     {
    . g; w2 C; ^1 e8 n  L2 \# W
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素+ Z8 B% I+ N" n7 X
  24. & \1 Y) E( \5 k& t! Y1 j
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
    6 A+ _- y! [- n) t6 ]$ t
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素4 h: a  a+ T7 l9 F  c1 B& n
  27. . c2 @& f. Y8 X
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素0 o) q: q: M0 r, P0 }
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符1 c7 w( l, O) ?" `7 W
  30. 5 p* A. D8 j* A8 |( H
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    - \4 y: Y4 ~, F: {5 v/ q
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    : T! e8 K- T* L  L& r* _
  33. & r( P7 N0 Q2 U$ a* P5 E( q
  34.       yOffset -= lineHeight;                // 更新y坐标
    - k& y& Y- z) j( g. G! Z" Y
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    / S/ {* K- k* V5 c9 c1 G/ W% s, h" T
  36.       textData = currentLine;              // 将textData指向currentLine' W" f6 f& S& K8 }% R2 w
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    + C( v  k+ a4 n- y1 s( `
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    - @0 K+ p1 x, Q( }0 X
  39. # J9 _% j* q$ W
  40.       if (lineIndex < numLines)) O- |8 c1 j/ }6 o7 a
  41.         lineOffset += 4;                   // 更新lineOffset
    ) P% A$ [* J8 w0 N9 s
  42.       ++lineIndex;                         // 递增行索引" `' }% S; R- z1 c5 f
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据2 f# d0 i' M" f: I. j1 p. B' x
  44.     }
    9 _8 S0 M3 F" ]- P2 M4 _
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    + V5 w4 Y! T+ L8 u( k4 i; {8 r- B
  46.     glPopAttrib();                          // 恢复OpenGL属性状态
    $ r0 }8 M3 U. L& X+ Y. F
  47.   }. A& Q* o2 v$ S1 h3 t1 K
  48. }) ^9 Z7 E8 l/ l4 x
复制代码
* u( L9 |+ A. t* o% y" o: `
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
; Z7 a1 j: L4 _7 V$ a' g' y
- e: G9 r  |0 zint xOffset,      字幕的x坐标+ G' s8 o7 ~1 w. D
GLint yOffset,    字幕的y坐标
3 B: r. |3 @# R9 tint numLines,     字幕的行数(较长的字幕为2,一般为1)
, \! D  \, \5 _2 q8 m1 H& Wint lineOffset,   这个需要再研究: X% W4 M( p! v+ `/ |
int lineHeight,   字体高度(或行高)/ a1 C( Y3 v. j, H
GLuint displayListBase, 这个字体对应的base值5 |5 o( A* \: B4 {6 K" w
char *text, ...         字符串
, Y% S- y; C- e+ N0 ~) G: w3 [/ i6 B8 Y( Y
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
, c9 E  O1 J% r: R$ a# `$ }
回复 支持 反对

使用道具 举报

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

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