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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
6 Q/ ?4 Y7 \, q3 s% L+ f9 Q9 J& e, f& c
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
  t. f( X, f. m& k因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。' |* {9 K; n0 `" y. w  t+ J  Y  b
https://www.chinaavg.com/forum.php?mod=viewthread&tid=1540819 w/ z- r1 `* ]- R6 M) p1 W
第1处4 _, s) L5 D# f+ v- I6 u0 G8 H6 j
  1. void sub_451474(char *a1, ...)( @. x" }" L6 d5 n9 ]
  2. {& t1 D6 x( J% \2 Y! y
  3.   GLsizei v1; // eax
    + f4 q8 W- g& t8 C( z
  4.   char lists; // [esp+4h] [ebp-800h]
    # h; m6 F( m% E+ A+ ]- c
  5.   va_list va; // [esp+810h] [ebp+Ch]8 w8 ]  p/ f8 w, P

  6. * i7 V4 M& B5 f+ ?# Z+ N8 b" ]$ g  o
  7.   va_start(va, a1);& o5 z. n. O! X4 ~: C+ A& O7 P+ G
  8.   if ( a1 )
    : C* j, O1 g3 X. p. |+ A
  9.   {! D3 V5 K2 n* ?+ N* r# `
  10.     vsprintf(&lists, a1, va);6 M" b6 n: I+ |# w
  11.     glPushAttrib(0x20000u);
    3 M$ r$ D/ m5 j; `* x& H8 G
  12.     glListBase(base);
    0 j2 U  u% v8 J" z& J% r- C
  13.     v1 = strlen(&lists);
    ; ^' P- ^1 j4 O. m/ ~) V
  14.     glCallLists(v1, 0x1401u, &lists);
    8 T. Y/ R. L, w9 G/ w; T5 o
  15.     glPopAttrib();
    2 V6 e- E. s) t( F$ C* I* C' w) N
  16.   }
    7 e; f  [! @& j6 F0 O
  17. }
复制代码
+ N7 d& r0 j  s  u# `4 ?

, v+ W; t' m5 T) |  c8 |" _4 F8 R3 e* |0 A1 N1 G, Z# z/ P
第2处6 C. `% S; x: n8 e0 k3 h
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
      {7 G& f  S$ A) C
  2. {
    9 D' e; m- j) ~6 v! |
  3.   int v4; // eax8 ]- j6 x6 V  X, O: l; k2 f
  4.   GLsizei v5; // eax
    " t/ W+ g/ O2 l  q4 |
  5.   char lists; // [esp+4h] [ebp-800h]3 D, o1 i6 w& Y
  6.   va_list va; // [esp+81Ch] [ebp+18h]
    ' E4 T) u% ?6 M1 }) Y% M' I" L5 o

  7. 9 s# K$ @, _. k5 d" s
  8.   va_start(va, a4);
    , U6 Y0 d# w; ~4 y# D
  9.   if ( a4 )6 j4 i, e# n6 H- j% S  s
  10.   {
    ( C: \& U) a4 I
  11.     sub_44F8A0(a3);
    " U9 f6 b8 n& X5 g. Z% O
  12.     v4 = sub_40BB44();
    ( x/ R/ `2 k7 h
  13.     glRasterPos2i(x, v4 - a2);7 `5 ^& g# C6 N7 _; g$ L
  14.     vsprintf(&lists, a4, va);
    3 Z0 o2 v; l! j6 a& n/ A7 m
  15.     glPushAttrib(0x20000u);
    3 |: a$ X" _1 Y: m1 f9 @0 \
  16.     glListBase(base);' x/ d3 g$ |; c. @
  17.     v5 = strlen(&lists);
    ' O, m/ N8 }" U9 n1 t  c  ^. u+ |
  18.     glCallLists(v5, 0x1401u, &lists);0 m1 F" R0 N7 K+ T7 x, r
  19.     glPopAttrib();& U$ g6 g* X, f
  20.   }& z8 K0 w7 R( p% n3 E3 h( F9 v/ ^
  21. }
复制代码
/ x; s# s* B3 H, b7 v7 m

' W) e" x7 I4 S% L
: M' J$ K) D( y. H) r2 @第3处
& @; ?5 U; C% P

  1. 6 r5 h8 v9 z1 C, S5 S. Y8 W
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
    ; [5 Y" q( S: L! S. q. f6 l/ u
  3. {2 K( {8 |) c9 P/ G0 n# ?! I
  4.   GLvoid *v7; // ST08_4
    * T$ _/ L: \6 J4 w6 E7 s
  5.   GLsizei v8; // eax+ ]9 R4 J( h3 S: A% a  q
  6.   int v9; // [esp+0h] [ebp-1018h]3 |9 d2 Q; g8 o2 b
  7.   char v10; // [esp+8h] [ebp-1010h]5 S# N- C/ v  v( I1 R
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]' J' {$ b4 {6 {/ ~! e, J
  9.   char v12[5]; // [esp+1013h] [ebp-5h]. }+ Y: `9 G: |+ o5 E
  10.   va_list va; // [esp+103Ch] [ebp+24h]9 [* S* C4 G1 H

  11. # |! b* v# @6 k- D3 `! i
  12.   va_start(va, a7);
    " G. }7 D7 {4 j4 ^! ]
  13.   v9 = 1;+ t4 ]& y* H2 _. a6 @
  14.   if ( a7 )- ^4 D& `4 o* }3 i& z
  15.   {) H1 i$ ^9 P; j& q4 h6 @$ X
  16.     vsprintf(&v10, a7, va);, @* z- i6 y2 c) r" K- t
  17.     glPushAttrib(0x20000u);  r9 y- W; q. O2 }
  18.     glListBase(base);5 A' }' c1 {. m6 U) ~
  19.     lists = &v10;* J/ n0 Z% c$ n6 @  v
  20.     do) z6 n4 J; B0 w% ]2 N2 B: y! D: o
  21.     {
    8 L/ p! a2 n9 Y
  22.       *(_DWORD *)&v12[1] = lists;
    8 d: M1 B% t) q& M( V
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )6 W& f% Q6 d; H3 r5 m0 ?
  24.         ++*(_DWORD *)&v12[1];- k- i" G* S4 _5 c8 S- K+ `
  25.       v12[0] = **(_BYTE **)&v12[1];  t/ L: {6 y) c
  26.       **(_BYTE **)&v12[1] = 0;
    6 [6 {5 D$ o. I) K& Q
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )% G/ K5 H. O+ L8 b' i) B# C
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    + Q6 W' q* w) B
  29.       y -= a5;
    ; J8 [4 J5 W% H, p; X) K
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    9 W, X4 N, W& n5 D
  31.       v7 = lists;1 n: n; h/ z' u4 n! h6 m! j
  32.       v8 = strlen((const char *)lists);* h/ e) M: ~: }7 x" \! T
  33.       glCallLists(v8, 0x1401u, v7);: p; T2 N9 k# N. A2 R
  34.       if ( v9 < a3 )% K7 H& g6 Q$ ]8 a1 k6 z# @
  35.         a4 += 4;4 N) ^+ i1 M  [
  36.       ++v9;
    0 ]2 `. A0 U0 }- l) t
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
    1 H4 a' Z  m9 f3 O8 S& K9 W9 o
  38.     }" P! Y! C2 [0 W& X# J. g; V
  39.     while ( v12[0] );
    1 l& _/ b/ ^( p2 Q
  40.     glPopAttrib();
    % ^2 b' G  e  S- N& N
  41.   }
    / a' t1 I5 b7 c
  42. }4 m4 m0 G! Y: h  E
复制代码
' |/ ?8 [$ M" T! C- P5 R2 ^
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
. j* d; {" D& M% C
: {' G) ]- [( O, _3 @! _$ E
  1. .text:004512B1 52                                         push    edx             ; char *7 U" ~1 f! _6 h4 B
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    4 I6 w1 f2 z# ]2 S# e6 q# {" m
  3. .text:004512B5 50                                         push    eax             ; base- R, Y; W' p8 s7 E
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    % Y3 ?0 k' r8 d0 ^( r
  5. .text:004512B9 51                                         push    ecx             ; int. s# S" x1 O  ]
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]% |  G" x3 u% K' Y! @3 }/ i7 X
  7. .text:004512BD 52                                         push    edx             ; int. A3 {( H& n+ T& I# W
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    / o5 C7 J- W/ m5 v7 Z* G- ^
  9. .text:004512C1 50                                         push    eax             ; int
    ( Q8 K4 i+ o$ k6 [5 y
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]9 L1 W% ]) S+ K5 k
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    # j1 V" Z4 m2 [
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    8 O8 u( F# P# l  ~! U4 |$ m7 d
  13. .text:004512CB 51                                         push    ecx             ; y
    " g; y0 k8 c3 s4 y0 H8 v0 p5 |
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    6 W; U) v* L) [' y/ @, f
  15. .text:004512CF 52                                         push    edx             ; int! r; s9 M- S0 [
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
  E  K+ Z' J5 r6 e: p# C% G6 Z
chatGPT整理过之后,如下
* a, I% j! M: P" }6 b4 @
3 w) g+ p- k1 u' H% A* _
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...); v: V( `, d" S
  2. {
    # b$ V' E' p1 I6 e9 f
  3.   GLvoid *textData;         // 存储字符数据的指针2 L( X9 f3 [0 e3 X
  4.   GLsizei textLength;       // 字符数据的长度
    , x( O6 W1 s% p
  5.   int lineIndex;            // 行索引
    3 r+ N( _/ {+ |/ L0 H
  6.   char formattedText[5];    // 存储格式化后的字符数据0 v# f2 L# q8 M& z  u
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    : ]; A8 w8 `" M+ Q, \" m- w
  8.   char buffer[5];           // 字符数据缓冲区
    ) a. h. I" H. a8 ]; Y! B1 T
  9.   va_list args;             // 变长参数列表
    4 u' G0 R- n& r  i- ~9 \
  10. " B+ \' `; L, ]
  11.   va_start(args, text);     // 初始化变长参数列表
    9 E, ^8 m! }1 [4 e9 E
  12.   lineIndex = 1;            // 初始化行索引为1
    % ?0 N3 x- o" ^# W/ q
  13. , _$ s9 A. `( l9 d
  14.   if (text)                 // 如果文本不为空
    + `, j: o# W) B5 e9 Y
  15.   {
    : p) K1 @  _# a. J* k
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中
    3 y  S6 ^$ P2 @) j% R7 m8 k
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态& c0 I! J" ]: W) z4 Q2 `% n
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    1 p) ?! ?& }7 j( ?" |# H. o
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
    * F8 u. a# V4 P( I

  20. 2 ~) N6 T; P1 O+ X4 p
  21.     do
      C. S* M  q" z+ {6 \$ r
  22.     {
    * g* G! M& z) m; u0 F
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素$ I( B& l& \4 |# x" \+ A/ Y5 W' a
  24. * V- c1 d8 U* L4 N* z0 x
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束2 X' c; I# f+ V5 L/ h
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    6 ~" o7 p% X9 I- g" i

  27. # Q+ [, S& l" ~; ?& }$ i( @
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素5 b; E. |8 ?1 x8 E& W0 \
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符/ Z5 M$ t$ \( ~! k8 [( `8 N
  30. 6 N2 f: z6 N0 n* T9 U% {8 [
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    5 N( \. T! z7 e! B0 M
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符" B* h# u: b6 E% r0 C
  33. 8 @& {: {- n9 Y, k; C( ~
  34.       yOffset -= lineHeight;                // 更新y坐标% R, t5 t% r" @9 v1 l8 x
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置8 }3 ~7 s4 i. ]7 C9 _/ a' d
  36.       textData = currentLine;              // 将textData指向currentLine
    $ ^  ?! F0 \1 l8 M0 a' z& K
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    1 w2 @+ G: R  L, f( b
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表' b2 H8 \+ b( @- e3 X' W9 W

  39. 4 ]4 C0 Y% j3 [2 @: X5 e& p
  40.       if (lineIndex < numLines)8 Q$ V, U7 C# q4 `- S. P9 {  R, W
  41.         lineOffset += 4;                   // 更新lineOffset
    2 P0 y; F% J/ K# Y# r
  42.       ++lineIndex;                         // 递增行索引! G: y6 y5 L8 O+ u
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据" Z; B- k, P9 s7 p7 V& ?! y
  44.     }9 ]" R: t* R- r- w
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    & M7 x& u0 j5 G6 ?
  46.     glPopAttrib();                          // 恢复OpenGL属性状态
    2 _. _: d% D: ?3 ~: w: p
  47.   }
    3 z' x- l1 v5 {9 J. @% d7 H
  48. }$ I% b* I" ]8 N" A  |; Y
复制代码

' V: Y4 F0 O" Y! w6 ?2 w含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前& ^0 p6 a- m. E9 t& O3 _7 ?' I. d
$ r% q: o, u  X
int xOffset,      字幕的x坐标' n. G( U5 g6 T5 M' a: f# c
GLint yOffset,    字幕的y坐标# l9 N) m4 s" s  G9 M
int numLines,     字幕的行数(较长的字幕为2,一般为1)
) ]1 }" d; _0 J) `; ?. u+ Tint lineOffset,   这个需要再研究: m2 h# c2 C/ Y% i0 o
int lineHeight,   字体高度(或行高)
. k, [7 S& E3 r- z5 C; QGLuint displayListBase, 这个字体对应的base值" X/ o$ ~: R/ V% O
char *text, ...         字符串
6 p+ F/ K3 D* U% @* v7 E- j3 |* [1 D2 q) k& s7 d+ l4 W( ^9 M
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好1 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
2 O( w$ j( X5 m" |
回复 支持 反对

使用道具 举报

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

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