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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
; B2 {8 T* b$ i% H  T) C" _- c/ c' r2 L# d. \- N
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎9 P1 S0 a% w. K- ~3 r+ X
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
3 ]1 M8 I7 Z& @! n4 {https://www.chinaavg.com/forum.php?mod=viewthread&tid=1540811 A& ]* ]1 e2 L9 i4 y- l$ `
第1处! ?' B& \0 b+ r$ q' Y/ x
  1. void sub_451474(char *a1, ...)0 {9 ?* U& z6 E. F: }/ y7 N
  2. {
    ( |. i4 L+ d4 C4 ]8 N
  3.   GLsizei v1; // eax
    0 A; n" f1 Q" P( n' f. ?
  4.   char lists; // [esp+4h] [ebp-800h]
    1 C: I, ~7 v/ u0 h) i
  5.   va_list va; // [esp+810h] [ebp+Ch]
    4 N" }/ a/ O- X- }5 {  }

  6. ! O- I% [6 Z/ i1 F
  7.   va_start(va, a1);
    ; u# U: b2 T/ ~1 Z$ N, [2 l
  8.   if ( a1 )% C) g% Q& x- O( c' v& l% e
  9.   {/ h! b$ p) a3 k8 H4 K% A9 F* V
  10.     vsprintf(&lists, a1, va);* m1 @, d$ |! @3 c
  11.     glPushAttrib(0x20000u);9 [  i* b4 J- [
  12.     glListBase(base);" _' A0 z4 Y9 I3 S
  13.     v1 = strlen(&lists);
    8 o- i2 J* I6 K9 M
  14.     glCallLists(v1, 0x1401u, &lists);5 G2 V; k- v2 J8 M/ x; O
  15.     glPopAttrib();" v2 B/ O( D1 p9 I1 p: F, Q1 r( F
  16.   }
    ( i# b  h2 H' h3 m; o; _0 W& H
  17. }
复制代码

! s# H( a% r9 J7 X1 @% P6 p7 E, G# k6 a& C; X- j2 j. w! N

3 S0 v# I' X  W) b- \; H' h第2处3 V* s  l* @" z, U& p+ m. j7 h
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    # J. w, k8 z. z/ u- H0 I, i. c/ ]9 O7 X
  2. {2 g9 K4 Z! \& F% h* |
  3.   int v4; // eax; \7 v6 {9 \0 x5 l5 k0 f2 z
  4.   GLsizei v5; // eax
    + q' M4 J# N  U+ @4 V0 L3 w
  5.   char lists; // [esp+4h] [ebp-800h]
    ( l4 M# D4 a- K, J6 J
  6.   va_list va; // [esp+81Ch] [ebp+18h]
    - c+ n, D/ w. j. R  n+ t4 L! v+ E
  7. # A5 j; }" E5 L
  8.   va_start(va, a4);
    : g7 W& Z. I! I% W' z
  9.   if ( a4 )* t( D" D+ p" M/ D; G0 y, b7 x& p# t" B
  10.   {
    2 s2 H1 w, Y3 V' x; x. V- c7 R# A# D
  11.     sub_44F8A0(a3);
    : s( n3 v: O" L4 \* W: C. A
  12.     v4 = sub_40BB44();4 q, X) ]4 b6 B) {( ]9 W* y- p
  13.     glRasterPos2i(x, v4 - a2);
    7 c$ S/ N1 N" |* |
  14.     vsprintf(&lists, a4, va);
    7 c' V2 g/ i# \
  15.     glPushAttrib(0x20000u);" S9 w6 i* o  D9 ^' D" h: Z5 w
  16.     glListBase(base);% U6 U2 i+ `/ T" v
  17.     v5 = strlen(&lists);
    5 A9 v0 A4 m6 F7 u* q9 d
  18.     glCallLists(v5, 0x1401u, &lists);
    " z4 K$ d, b9 p$ N; t+ i
  19.     glPopAttrib();: B% Z8 W% G3 C$ t1 {
  20.   }8 p: ]+ j. T; L. ~" G
  21. }
复制代码

3 b! e! ?: n8 D9 ^/ J6 P3 r7 t: I+ \1 {0 \) m' f

& ?5 B, ]/ Q0 [% \第3处
) V7 j) V$ c5 J; u4 H6 B1 P1 b

  1. ( g+ n! V* f- q" _
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
    0 z' o4 z2 S9 c
  3. {
    $ s0 B, ]/ b# |, C
  4.   GLvoid *v7; // ST08_4
    3 U2 Y, n: J6 w/ [. q
  5.   GLsizei v8; // eax
    4 M3 S  b& ~( r. z# H
  6.   int v9; // [esp+0h] [ebp-1018h]
    / e/ T7 U! R0 |! [
  7.   char v10; // [esp+8h] [ebp-1010h]
    ) v: S# B$ ]8 p- l4 e; g
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    + r0 D* g- y! _/ X3 e
  9.   char v12[5]; // [esp+1013h] [ebp-5h]7 A7 h8 y$ ]; S- H) \- Q1 u6 s" c
  10.   va_list va; // [esp+103Ch] [ebp+24h]
      r- u% a, [) E+ c3 o; M

  11. * A5 ^2 L# s( S2 X0 U4 k% j  Z' n
  12.   va_start(va, a7);0 m3 z8 _) C+ `7 n4 n* d! a) o% O
  13.   v9 = 1;
    : }) a1 j! L" `2 q) I1 ]) {/ X
  14.   if ( a7 )6 G& X1 ?* y' M6 a( z0 t# I" w
  15.   {6 u% d' ]/ D) A5 H
  16.     vsprintf(&v10, a7, va);9 v9 E% ?8 u2 y" T# o
  17.     glPushAttrib(0x20000u);
      j* {1 l6 Z2 |
  18.     glListBase(base);
    - J/ W- s, D8 d' a/ y' ^
  19.     lists = &v10;+ ^0 g1 f& k- W# }/ T
  20.     do
    " b. I* [( e# T( d* M, _
  21.     {
    - X% [/ _! R2 m5 @. y5 x
  22.       *(_DWORD *)&v12[1] = lists;6 ]8 x+ G$ J3 F. e5 q' w( ^  z
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )" M% }9 G$ i, f/ Z: }; Z
  24.         ++*(_DWORD *)&v12[1];: U" F' d# ?: M8 ?' i1 k1 b
  25.       v12[0] = **(_BYTE **)&v12[1];
    & e/ u& K/ Z; ^4 m1 ^" O
  26.       **(_BYTE **)&v12[1] = 0;( g. O" M. P/ W' C8 d
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 ), `- G, o. P: e  X$ g
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    1 a; i, l6 l2 S
  29.       y -= a5;$ V& Z) L7 u1 _; b) Y
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    - L( V) m( O7 E( c& h
  31.       v7 = lists;
    , ]* P" ]# d& D1 y& a
  32.       v8 = strlen((const char *)lists);4 V9 y5 g) i6 Z9 C* I  R& G
  33.       glCallLists(v8, 0x1401u, v7);/ E+ A( m7 ?: S: T& K1 ^2 ]& N: b: u; P
  34.       if ( v9 < a3 )! W* P1 X2 I9 @1 n4 u
  35.         a4 += 4;* p2 r0 \+ f. i/ N6 _) l7 Y
  36.       ++v9;3 k" l  \2 ?' a) U- F
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);3 X" }, j7 v- d  [% Y5 {* C9 w* P8 L
  38.     }
    ) C) Q3 z$ w: ^" i( J0 V
  39.     while ( v12[0] );
    / Y. ^. a0 [- C
  40.     glPopAttrib();1 _, Q$ h6 E$ w
  41.   }
    - |/ ]- d' f' i7 _% X7 Y
  42. }
    * D; H" Z& F! J; p2 k% L$ j
复制代码
  D  h8 }9 ^5 [8 e& F% @2 P
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810# i. {+ w# W8 j7 R, X3 R: K' p& M# D

% d0 x* s6 S! \2 }! K
  1. .text:004512B1 52                                         push    edx             ; char ** B  Z9 a5 S, I$ C+ @6 O( R, a' v4 A
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    - E# z7 ?/ J$ k& B9 U: O
  3. .text:004512B5 50                                         push    eax             ; base
    ! F# T3 j! {1 R; J% M
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    + O2 L. e8 _( p, Q) h" @
  5. .text:004512B9 51                                         push    ecx             ; int7 m9 J( S( K( |7 n8 r, v
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]+ E( ~# _7 J$ H' _7 }
  7. .text:004512BD 52                                         push    edx             ; int' M5 Q: w1 b4 K+ O7 j2 E+ x
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    2 F  X. i* V$ l! a9 z
  9. .text:004512C1 50                                         push    eax             ; int
    2 u" ^9 E. M& T8 q8 u
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]) C: ^  P2 T! o
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]+ T) A; M6 B  r% F) ~! B, d8 G
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    1 @3 E! ~( ~4 b
  13. .text:004512CB 51                                         push    ecx             ; y
    / J" s$ X( X; s" p8 J
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]* j- ^9 `, y7 s
  15. .text:004512CF 52                                         push    edx             ; int
    * I3 A; J7 n. @* x
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码

3 Z+ `% D; D5 j# ^, I+ x# }+ cchatGPT整理过之后,如下" E" h' o7 X; G" B

9 T2 t9 a$ {5 R/ K& o0 F0 @
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    ' E4 _0 T) L, c, p  h$ _
  2. {
    : Y4 `  [- w+ W) r# r7 x
  3.   GLvoid *textData;         // 存储字符数据的指针
    : M$ J- E; y7 z9 k/ v* E7 O
  4.   GLsizei textLength;       // 字符数据的长度
    3 I3 r. {# e/ `! J9 M
  5.   int lineIndex;            // 行索引
    9 x" p4 U+ G5 W
  6.   char formattedText[5];    // 存储格式化后的字符数据& z9 t8 I# V# D; J" g: b4 p1 d
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    " q6 f3 T8 h6 a  C0 v) ]% D, r
  8.   char buffer[5];           // 字符数据缓冲区7 o( ]( S6 H1 W7 j) z* k
  9.   va_list args;             // 变长参数列表
    0 ^  m$ H/ T: v
  10. 2 C$ m/ n+ l* `& S+ b- r* v+ @
  11.   va_start(args, text);     // 初始化变长参数列表7 M; M2 N, q) Q* b
  12.   lineIndex = 1;            // 初始化行索引为1
    7 W9 K9 u8 L0 o/ ~% W+ w1 c

  13. ' i" n& K- o5 z7 O% V. i/ }1 z
  14.   if (text)                 // 如果文本不为空
    % j5 y8 z$ P6 n' S4 p
  15.   {
    % ~% O3 u' t6 [
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中" Q- I+ g4 @7 d+ F8 c" T
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    3 Q% [$ p' N1 U8 l
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    - r, W- p- _, }. k: _2 \/ ^! g$ v
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
      [1 p+ k. m( a; C

  20. 5 O6 m* _  Y+ V: _# ]
  21.     do- C8 k5 }9 @% }
  22.     {# ~0 n) Q8 Q# K, E& H
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素2 E, H% v3 x: f1 p$ h+ U9 o6 l( D

  24. : W1 ?) _( G2 s4 e
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束6 q7 `+ z9 H2 v2 b( n
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    1 ]0 a. ]% O- Y9 r! w
  27. / {* c! u* m/ K# J2 `1 q
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
      @: y+ m% w! x" u/ }4 q. I
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符, c5 ^' y' [: S3 ]0 T
  30. ( Z# W5 i4 l$ z: N
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    ! a. Z4 `& W, `3 {% |' V
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    ! H; P* K' B0 z& d

  33. $ |1 _1 ?( I' `7 j$ \" |
  34.       yOffset -= lineHeight;                // 更新y坐标
    # o/ O4 I7 _' F- `( Q
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    5 n& e; v$ s/ W/ Y  @/ b
  36.       textData = currentLine;              // 将textData指向currentLine
    3 H6 m, t* S- y
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度' Y( p. Z- `- {( S1 @
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    1 H& Z4 v! r4 g3 u

  39. " o6 [$ E3 T( j- ?. `+ e  p9 J
  40.       if (lineIndex < numLines)( C. e  [% t. b4 a, `1 s( R* W  i
  41.         lineOffset += 4;                   // 更新lineOffset& M% [5 l5 @! f. v9 o! F
  42.       ++lineIndex;                         // 递增行索引
    $ G/ \4 e8 e& z* _  @; T
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    9 z2 q3 @% ?# ^8 q
  44.     }
    - e. [) o. a  f
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环4 s  e8 e( b8 Y- F1 _3 z1 P- B
  46.     glPopAttrib();                          // 恢复OpenGL属性状态, L2 e2 f! ^1 q5 X7 Z
  47.   }5 \# r- P1 Q! T7 T( R6 _
  48. }  X$ I5 n, X' i7 e; ]
复制代码
3 U5 Q3 B  b* T( x
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
8 t; D: p0 c+ F+ k! f
/ j1 t: Y) p  I4 w' e8 y* i) e/ nint xOffset,      字幕的x坐标
" S9 [! ]3 @* G+ AGLint yOffset,    字幕的y坐标' `2 d; T  {% W
int numLines,     字幕的行数(较长的字幕为2,一般为1)
1 V/ K6 s  B. A: n  Sint lineOffset,   这个需要再研究
+ |9 \, X- w5 Y6 @2 O6 [: x8 |int lineHeight,   字体高度(或行高)
6 C& N3 T! y2 W9 c  H" l- X) bGLuint displayListBase, 这个字体对应的base值' ]1 g- B3 L. [' l1 a6 V! B
char *text, ...         字符串
  f- [7 T. ~) N8 d. y
9 R& y. v5 K8 o& r. X
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好1 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
: W7 {. P3 H4 H
回复 支持 反对

使用道具 举报

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

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