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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
# n: \7 l. \# D+ ]: \3 T: [+ z
( B0 |( _" H& C- {4 K" L这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎2 Q6 j2 w$ t. |/ v) R* ]7 u9 P
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
1 S. F+ d9 u$ G* p1 P  qhttps://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
1 e' |% C' K! S& d1 }8 u7 K第1处
+ Z0 Z" ]( d7 l9 ]7 |
  1. void sub_451474(char *a1, ...)0 d9 @1 q) d, v1 s7 c
  2. {6 l: e1 |- @5 z/ S3 h( K
  3.   GLsizei v1; // eax
    0 L1 ]% x0 q* g: g( T9 h# h
  4.   char lists; // [esp+4h] [ebp-800h]
    8 V- Q9 _& L; D7 g" x
  5.   va_list va; // [esp+810h] [ebp+Ch]
    7 t4 [( @# ^* g9 X

  6. & l8 n  G+ w/ \) S4 I; D7 ]
  7.   va_start(va, a1);' |) x0 _" l3 z6 y) j9 z  w
  8.   if ( a1 )
    1 A' C' S, T9 b# i% j4 ]
  9.   {' V8 P# ^9 S  i  @7 \* w
  10.     vsprintf(&lists, a1, va);
    - {  b: _8 A  l
  11.     glPushAttrib(0x20000u);
    3 L. w6 a' h7 r7 L& r
  12.     glListBase(base);3 p3 q. i2 z2 G7 b
  13.     v1 = strlen(&lists);
    : r' f4 K( U0 E0 I
  14.     glCallLists(v1, 0x1401u, &lists);% e' d; N8 k! |  [+ o4 ?
  15.     glPopAttrib();
    5 r' U5 @; R) B+ t7 @
  16.   }0 [* u/ g: D% A3 g4 W5 ^; m( l: o% b
  17. }
复制代码

5 B% Y. B0 H( F0 b$ V- g
$ t5 \% P- ~; z- t
% l1 G  _5 Q; K7 w+ x第2处  e6 z, Z  Y* z1 @  n; e
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    * M$ p+ u8 ?2 q8 ]0 i- g7 a
  2. {6 ?% |9 X( F5 N$ e4 ?' p- k
  3.   int v4; // eax* T" w! b, ]# a$ T* `) @
  4.   GLsizei v5; // eax
    2 D8 X% V) u! i* b
  5.   char lists; // [esp+4h] [ebp-800h]
    9 E+ o1 L) r; @( W; y- x
  6.   va_list va; // [esp+81Ch] [ebp+18h]! Z* _% h/ y' D, ?
  7. 1 u/ D% q$ Y) Q5 ~7 l" ]
  8.   va_start(va, a4);
    4 P5 Q+ c/ r1 Z
  9.   if ( a4 )2 D' e: |9 b, }/ W; e4 b- [0 `
  10.   {
    ; x6 m6 R" C/ _9 ~6 u
  11.     sub_44F8A0(a3);
    0 f' N- q+ Z* ~
  12.     v4 = sub_40BB44();
    ) _& w9 }* P; R2 h+ m: `2 ^
  13.     glRasterPos2i(x, v4 - a2);+ D) r# g" D! x( |$ C
  14.     vsprintf(&lists, a4, va);& ]7 ?+ f. M6 |' a9 N
  15.     glPushAttrib(0x20000u);
    7 m) s" ]7 w# S: I2 t  H& r
  16.     glListBase(base);
    + a! D, }3 n3 o5 B, J
  17.     v5 = strlen(&lists);% W, s. \0 J3 }" ~) q4 c
  18.     glCallLists(v5, 0x1401u, &lists);7 {% S3 |9 D9 r9 j
  19.     glPopAttrib();9 Q% ~2 M# e, D' T
  20.   }/ W) B( d! s' H3 G7 w: z  ~
  21. }
复制代码
4 L' x7 K6 A$ t1 @5 H7 J3 A7 a

! S  e' d0 o3 N8 L+ `6 S$ n* b* v$ ^7 y1 D7 n2 N9 F( N) ]) F1 I
第3处" M7 J) _9 W' @+ M# Y; ~: m5 y
  1. ! D2 ~/ @7 @% k1 [
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
    ( F  [+ {( G& K! C& \1 I
  3. {3 X; q) x, X1 z1 ?5 f, |
  4.   GLvoid *v7; // ST08_4
    1 L& T0 {5 U7 k# [) b4 a- y. i
  5.   GLsizei v8; // eax
    7 y  O$ ]8 Z, U! Q
  6.   int v9; // [esp+0h] [ebp-1018h]
    , V2 S* d; M$ z
  7.   char v10; // [esp+8h] [ebp-1010h]+ C2 |0 a6 n" B2 s
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]; L9 [7 B  \. B2 `! x5 u( a' ]3 u4 f7 S
  9.   char v12[5]; // [esp+1013h] [ebp-5h]; q4 p0 b  H6 h1 U0 q( G+ ?
  10.   va_list va; // [esp+103Ch] [ebp+24h]% W3 K$ g0 t: C' @* [

  11. 2 v* P# y# \. {4 H  b" ?+ J
  12.   va_start(va, a7);+ {% ]6 {( G6 ?4 `: y
  13.   v9 = 1;1 @$ A3 S8 z: T# B2 V
  14.   if ( a7 )
    ! ^% d  \3 X/ Q
  15.   {# x2 t( y# v! [% }3 [0 P6 K' r
  16.     vsprintf(&v10, a7, va);
    9 `3 I( X2 \7 Y5 f0 D. ]! V
  17.     glPushAttrib(0x20000u);5 ~: Z2 i0 S5 M# B% T5 p- q, c/ X
  18.     glListBase(base);) ?- j% }/ ?* q7 R/ u5 |5 h
  19.     lists = &v10;6 q7 \: x9 O4 s; M
  20.     do
    7 _1 h5 B# m; ^5 u8 T
  21.     {% r+ C9 A! f* x4 q( J
  22.       *(_DWORD *)&v12[1] = lists;
    # u/ }' O4 T: \. [9 X! I
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )" C, X( e2 Z2 o* k! V
  24.         ++*(_DWORD *)&v12[1];
    6 ?* r  s/ D5 z. t: Z
  25.       v12[0] = **(_BYTE **)&v12[1];
    ! \; [$ o) P% w0 A0 O3 K
  26.       **(_BYTE **)&v12[1] = 0;- a7 Y0 f+ {3 E% X4 K% @
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )! h7 ~0 G2 x" x+ u8 `
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;* [% _# h- y% x$ r  a
  29.       y -= a5;
    ) h5 W+ r, K0 e& u
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);+ R( g3 b- `+ ?' Z$ s# E5 }& }; r
  31.       v7 = lists;
    4 A- _( g, ~! m3 b" H, P
  32.       v8 = strlen((const char *)lists);
    . g) x# f: ^* l% g1 O
  33.       glCallLists(v8, 0x1401u, v7);! a, ]; V0 e1 v3 ]* c: V/ L0 p) i
  34.       if ( v9 < a3 )! L; s* f: {) o  U" ]: G8 z
  35.         a4 += 4;
    # e  Z7 r* e1 ~: |5 h; F
  36.       ++v9;/ A7 Z0 b, V: q# A  O# |
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
    + r; e7 E" \) Q$ }5 ?) U8 u+ v
  38.     }
    3 k) w( F2 A- a0 a8 Q  b0 \, t
  39.     while ( v12[0] );
    6 Y# a3 p  i4 r( {( R. Y+ s
  40.     glPopAttrib();) [6 p+ B! d2 c. W5 G1 Y1 L7 H9 @
  41.   }5 p+ D: i5 y7 i( [4 H% g
  42. }/ w) |8 a$ H& m
复制代码

7 ?1 u, m  Y' C) ~) h调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
. ]4 C7 H: s9 c( E2 \) g. s. L8 C6 A+ F! B& |9 Z5 f  o' |
  1. .text:004512B1 52                                         push    edx             ; char *3 ?+ u1 Q2 y: o7 @+ ~
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    7 t; |5 F  c" e# g; U% M
  3. .text:004512B5 50                                         push    eax             ; base0 f5 d4 b& C5 y1 N7 E/ l3 S2 ~& H
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]4 m# L2 M3 ~) g0 U" R- U" m
  5. .text:004512B9 51                                         push    ecx             ; int
    . x! Q. e, E/ z6 o4 S* z
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]
    . N5 n* \" R# s! N$ q6 i6 N
  7. .text:004512BD 52                                         push    edx             ; int7 L  a7 G$ g4 J4 f7 ^. l( T
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    0 D9 [1 ^/ L  G8 d1 v
  9. .text:004512C1 50                                         push    eax             ; int8 u1 |) ]2 J* ^( k2 ?2 \9 D# W
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]( T6 q& a. G3 {1 i
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
      D' c, ~) h# ^
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    , g& x9 |  c3 W" l5 V+ ~
  13. .text:004512CB 51                                         push    ecx             ; y" |; z! y6 J2 z0 |! Y
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    8 x# A6 E# [; i) ~* |3 n  B
  15. .text:004512CF 52                                         push    edx             ; int* E( w2 {2 l! {/ P! i2 J; `5 G
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码

1 f3 s: o* r9 a3 c" mchatGPT整理过之后,如下% d* Z& `) j- T$ [! l
- W5 ]  O7 p9 @
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    1 ?: K6 G0 N2 B5 G3 `" S
  2. {
    , B# _0 ~9 w5 G7 u! G& I& u) G
  3.   GLvoid *textData;         // 存储字符数据的指针
    ! J$ t7 d9 B% d( f( \
  4.   GLsizei textLength;       // 字符数据的长度# R2 u  y) s9 F6 K
  5.   int lineIndex;            // 行索引
    ) a# u0 T4 F, A+ }2 ~
  6.   char formattedText[5];    // 存储格式化后的字符数据
    3 P+ S( n" o& `/ M  B
  7.   GLvoid *currentLine;      // 当前行的字符数据指针% @1 g5 D" i  A( J
  8.   char buffer[5];           // 字符数据缓冲区9 L2 }/ C/ w% Q) @) j. i' j1 L
  9.   va_list args;             // 变长参数列表
    3 z& n5 E: A: P' I( i

  10. $ L" }" p6 C$ X9 }& X
  11.   va_start(args, text);     // 初始化变长参数列表8 G7 Y( K) y* Z: Q- N$ q3 Z( l
  12.   lineIndex = 1;            // 初始化行索引为1
    % n0 z1 ~3 c! R4 Z" Y
  13. : S9 d( L) `2 \. |5 }" |" A
  14.   if (text)                 // 如果文本不为空1 g0 O" v$ [! t1 ]4 ^2 u
  15.   {
    : V( a7 E' S1 @# c( b1 g  f- A. P
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中. z, P5 w% j2 g
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    6 N( Z! V% ?6 i  a
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    + C+ Y' H/ k" u
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置  M6 A" O+ `3 b$ G1 @' s& D/ h

  20. 4 A0 L! _1 N1 o/ J
  21.     do
    6 G' Z- p! B; x0 T& v3 B2 l5 \
  22.     {* }7 S( _) @# ~- h  p& C
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素8 @" z( v% }* R( b5 @4 X  A  _
  24. , Z! Y+ p6 r( u- Y) }" [
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
      k  x; T% \. O+ s8 Z* G* S
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    2 r* K1 u& Z: X

  27. + m1 R( C/ x1 w5 G2 i$ f3 M2 M0 S
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    ( V7 M! l9 {: Q# p, x
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符+ T# n& `; o0 V
  30. - V. B! ?. z& |9 v
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    ; C+ l3 b2 r- T
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
      {4 \4 M' F/ M6 S" a  K

  33. 0 r$ c7 W: |2 V; r1 Z
  34.       yOffset -= lineHeight;                // 更新y坐标
    ; x3 G" Z+ j, N: i9 j/ a& p
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    / M9 C9 D, B% V
  36.       textData = currentLine;              // 将textData指向currentLine9 X, t% R$ @7 c( Q3 g5 a
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    8 z, [% c7 k& e9 _* g+ ]& }& c* ~
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表9 E' }/ a6 ~3 W

  39. * O' n- r3 P' y  ~( O) A; R9 x
  40.       if (lineIndex < numLines)
    + G; G8 H) H# g4 M
  41.         lineOffset += 4;                   // 更新lineOffset
    ) }. r9 v0 c* }4 c  T# ]; U* Q
  42.       ++lineIndex;                         // 递增行索引
    . ~+ n& D" d0 H4 w# S; w
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    ' \! A+ |6 {4 f
  44.     }
    ( z$ z- H" \( l5 _1 I; {" z9 S
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环4 c% H! Y9 T, [. Q9 s
  46.     glPopAttrib();                          // 恢复OpenGL属性状态$ O8 v1 i2 l& f2 [: _; o& w5 c
  47.   }( r: g2 v) f. ]0 O" d: P7 D7 t5 g
  48. }
    - u* d8 E) v0 T" j: q! j
复制代码

" }% T) o8 L% q0 R含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
6 C4 v: ?3 K- J: H% ]0 }7 t4 N& I) L# B# @
int xOffset,      字幕的x坐标
: [1 C! A! |2 U3 mGLint yOffset,    字幕的y坐标
8 B8 S9 R- i$ g2 r7 _$ wint numLines,     字幕的行数(较长的字幕为2,一般为1)
0 ~4 N6 M$ ?: lint lineOffset,   这个需要再研究4 n( i2 f$ A7 e3 N% e
int lineHeight,   字体高度(或行高)
6 G" `: C( z2 @4 C/ A0 oGLuint displayListBase, 这个字体对应的base值4 v, T- {/ P( O! z! j3 T& X- k
char *text, ...         字符串) C7 B& x( E' y/ w; b4 }5 S
7 h: y) V! ]6 w$ h2 O% q  t  h& ]
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来% X7 S* G" o' D* `
回复 支持 反对

使用道具 举报

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

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