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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑 + u" I" @' Z4 |& g( n" |/ {9 k' B# y
7 n  `/ Q2 _" b: y2 j
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
! Y8 e, b3 v+ r8 G' y0 l因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。/ W0 s5 k/ y) M8 z. o
https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
7 \/ O) B. m$ Q* {第1处
/ `* v$ t6 C" [, i
  1. void sub_451474(char *a1, ...)" ]3 }: Y  y( k% Z  _
  2. {% ?" k3 a  u9 C9 u) r$ M7 |
  3.   GLsizei v1; // eax
    4 Q9 r* T, v4 }' r! f
  4.   char lists; // [esp+4h] [ebp-800h]
    ) _& l5 [, q6 g+ Z
  5.   va_list va; // [esp+810h] [ebp+Ch]% M7 n- j8 K" D4 {
  6. . z+ @" W' J  s' F, t% i
  7.   va_start(va, a1);
    3 Z% y7 g  [1 |- H. m
  8.   if ( a1 )& q3 W6 l: U* `8 A
  9.   {
    " l7 Q0 z* S% `7 w0 y
  10.     vsprintf(&lists, a1, va);
    " i- t2 L$ J% d
  11.     glPushAttrib(0x20000u);' {( [% z) |) M+ i
  12.     glListBase(base);) a0 c7 _* p& g# b" W$ u. P9 \7 O
  13.     v1 = strlen(&lists);
    + ?# V2 A9 t0 T
  14.     glCallLists(v1, 0x1401u, &lists);6 Q& N& Z5 c% x" ]) r
  15.     glPopAttrib();. T- u+ q! `/ v* a
  16.   }2 D8 x5 {% ^, [& h
  17. }
复制代码

* `0 r3 p5 O1 Y% n
2 f5 L  f' F" r0 @1 B! a4 B$ h. J7 _5 a6 \) |6 A! D3 O. x
第2处9 J! d) t! k, \8 `7 W3 K! z
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    ; h! F5 T5 }. `( s9 A- q' U
  2. {3 f2 F7 u9 ?7 x7 m4 p
  3.   int v4; // eax
    - U4 L/ D2 `( X% N+ q/ e' r; {1 }
  4.   GLsizei v5; // eax; j( M4 z5 m9 i6 c) W' B* U( b  M2 C
  5.   char lists; // [esp+4h] [ebp-800h]+ D% b# \% l$ i+ K- O
  6.   va_list va; // [esp+81Ch] [ebp+18h]( J: q! L+ r" m

  7. $ c/ C" u6 [8 _
  8.   va_start(va, a4);6 m, [! [3 s' {' G
  9.   if ( a4 )4 s  A% g+ }: y! t" _
  10.   {4 [/ ~, _- Q/ G$ V' z6 `# b) b9 F2 E
  11.     sub_44F8A0(a3);
    7 {: u1 V& E8 S3 s
  12.     v4 = sub_40BB44();
    5 Y6 H( E) ~# V4 I3 j2 R* r" {
  13.     glRasterPos2i(x, v4 - a2);/ Y) @7 _( i6 p* L1 d8 Q; Y0 ?
  14.     vsprintf(&lists, a4, va);
    - `/ v3 }, c$ Q/ W' O! F& U) a
  15.     glPushAttrib(0x20000u);. H, \4 D  y4 X- E- p, [8 L6 b
  16.     glListBase(base);
    6 Z6 z3 T2 c- u
  17.     v5 = strlen(&lists);
    & }% a/ v; i. i: p& i
  18.     glCallLists(v5, 0x1401u, &lists);9 Q5 U( y3 b# w, @' o
  19.     glPopAttrib();7 k  j! W! }% H2 P% R
  20.   }( a+ m6 [* J4 y$ E4 v4 i, b5 h+ K7 y
  21. }
复制代码
$ t/ Z& c. Z1 B5 r) q& x. C, t
' R9 Y" r, X' e. d) Q

$ e5 R% A6 C4 u: s第3处
& Y1 S9 m2 D! k$ ?
  1. 4 @' g: L# c7 K& e6 J" X
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)9 @1 u' Y# k6 |
  3. {
    9 R) g& @5 x5 j" z
  4.   GLvoid *v7; // ST08_4
    0 c/ D9 w5 _. e# ~1 e4 l
  5.   GLsizei v8; // eax
    . P7 D. W- F( j7 N& C) X
  6.   int v9; // [esp+0h] [ebp-1018h]
    0 q$ ?; r" e7 i( y: `4 L, L: q
  7.   char v10; // [esp+8h] [ebp-1010h]
    $ ]: |0 T1 Y% T: a+ `
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    0 t4 d( o6 R3 C# ~
  9.   char v12[5]; // [esp+1013h] [ebp-5h]
      z; j0 d& h  M1 o: @6 t
  10.   va_list va; // [esp+103Ch] [ebp+24h]
    0 _2 K8 C1 Q+ `7 |
  11. 8 b" U; U2 r$ f! u. B4 o; n* D" g$ K, L, D
  12.   va_start(va, a7);
    : t& ?# P3 t; G
  13.   v9 = 1;
    % N; \/ @# Q# V  ~2 @5 i& {8 y
  14.   if ( a7 )! \0 [1 H1 i- a
  15.   {' K+ N. m$ w( {) p& i
  16.     vsprintf(&v10, a7, va);
    & v, U0 y/ e/ _& q; i. h! f0 k+ s9 v" m
  17.     glPushAttrib(0x20000u);( Q5 k! F6 l  W9 p9 r
  18.     glListBase(base);
    * F3 n8 N! J9 S& `7 j& O
  19.     lists = &v10;
    $ u! H8 E" J2 G% P5 P# H" d+ u
  20.     do; y; j3 ^5 a: G. Y4 D* i' I; f6 [
  21.     {
    ' J2 Y0 C- f, ?; h4 O
  22.       *(_DWORD *)&v12[1] = lists;. i4 g, U7 {% h5 O& x
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )0 _' @0 D7 }7 Q% F
  24.         ++*(_DWORD *)&v12[1];& }# K* z) g$ r; y/ W
  25.       v12[0] = **(_BYTE **)&v12[1];  H2 U% h, i3 v8 n8 x  {/ ^) m3 O
  26.       **(_BYTE **)&v12[1] = 0;% U1 v5 H  v2 E
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    , h# t6 i7 F. g8 _7 y( K
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    ; i; Y- {; s/ [$ V" M
  29.       y -= a5;
    9 D  [3 E" t- f" T, I. D
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    6 h+ R0 {( l: G7 R7 g& c
  31.       v7 = lists;" ^+ m3 p; P- @5 {
  32.       v8 = strlen((const char *)lists);' ~# t9 Q' B- ]& P1 u
  33.       glCallLists(v8, 0x1401u, v7);
    ' g5 g, S' O/ t. f2 Y& ^
  34.       if ( v9 < a3 )
    * ~# I" Y# K7 n  M- {- ^
  35.         a4 += 4;
    # D: |: S5 m# w
  36.       ++v9;
    1 Y* A) w% k1 X- Q/ q; y! V3 V
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);  U: ?8 g9 H7 P$ @7 ^/ @* c
  38.     }
    + H6 i; C) w6 ?" Y- p" M. N
  39.     while ( v12[0] );; O5 a% K# C: `* q3 c) G
  40.     glPopAttrib();$ ^' @- e& ]8 T8 L
  41.   }
    % ]- G: U* o) Y  M. p( _
  42. }
    2 v) u( U1 U) R
复制代码

# n* C" c, J5 Z5 C  d调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_4518100 _- o3 J1 t8 [1 g
- M$ \1 E9 V' m4 V
  1. .text:004512B1 52                                         push    edx             ; char *
    7 T* H+ P- m( b8 ^0 e
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    " X4 @8 N+ C" Y( l$ e) ^1 i. K
  3. .text:004512B5 50                                         push    eax             ; base  g4 @/ a! [* q" {
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    ! N" b& C, y* C
  5. .text:004512B9 51                                         push    ecx             ; int
    2 R4 c' w8 g+ H% g. S! D
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]- O$ r8 D. C3 M+ `, r& E
  7. .text:004512BD 52                                         push    edx             ; int- Z7 ^7 d$ I- H' ?2 w4 i
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    ( i& A+ L7 Y0 ^- L/ p/ A: }* v3 B2 y  ?
  9. .text:004512C1 50                                         push    eax             ; int
    ( X+ f& `% N9 `. U
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]3 X2 R- F& Y0 K
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    ) q  M* a7 H2 N7 z1 f$ V" [
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]) N6 o+ |2 b' _! W6 {
  13. .text:004512CB 51                                         push    ecx             ; y
    3 z% H  O1 a1 J) Y' b2 I. V
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    # T" |9 j2 s: p
  15. .text:004512CF 52                                         push    edx             ; int
    * z& M& O! j) [5 _
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
# W  {  z: T  w4 X" e6 d
chatGPT整理过之后,如下: {# P! b) [& B+ N+ ]6 y! g

1 j" j, D7 ?# V% `
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)) `. O  c4 T& u4 N) g) c
  2. {
    0 j' a/ r! Y- j1 x) {" c
  3.   GLvoid *textData;         // 存储字符数据的指针
    , n6 G4 O. l: _, q: M) A
  4.   GLsizei textLength;       // 字符数据的长度9 M8 h- ~* u1 M. e5 [
  5.   int lineIndex;            // 行索引0 ], M2 C, x2 Y
  6.   char formattedText[5];    // 存储格式化后的字符数据
    5 V' ~" N6 f5 w
  7.   GLvoid *currentLine;      // 当前行的字符数据指针1 g+ I5 y8 w9 G1 @7 j
  8.   char buffer[5];           // 字符数据缓冲区
    ' `' h- X4 _: _# q4 `
  9.   va_list args;             // 变长参数列表
    / G1 h1 m+ a9 p

  10. 9 F, s4 s- v/ }& T
  11.   va_start(args, text);     // 初始化变长参数列表5 f$ N6 K8 o. E6 ~4 G' Y( J
  12.   lineIndex = 1;            // 初始化行索引为1
    7 o+ B4 E: g( S$ ?
  13. ( V: k$ \& g% X  r8 S
  14.   if (text)                 // 如果文本不为空( _% m0 M! e7 {& z  P' b8 h0 e+ f
  15.   {
    ; \/ n, o) Y( B3 _
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中4 c, Z9 B7 W# j2 D
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态* |3 z. e+ v: K9 S3 \3 H
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    * L; R& i  F1 [8 i* R$ c" L
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置. w5 r4 T4 p: i8 q
  20. 3 d% N& \! w) w& p
  21.     do
    3 x$ _& K0 y  A" v9 ]4 H6 @
  22.     {
    , c. E; q4 e1 B  K
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素
    1 I7 _* I+ G# v, h2 q" u

  24. 2 `7 X& G. i! k. B& w% X. l5 u
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
    # H0 Y5 i. C8 k. H1 ?
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    . @2 `: O' \5 ~2 }+ s  U2 s" C
  27. * ]0 O3 p, q" w0 y' g  r
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素' O& G$ N; C4 G7 A5 M" y
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符2 @' \0 v* s$ n" i7 k3 j) ~

  30. * w9 k4 T  e' G' p
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    ; \- Y2 q5 h9 u+ ~
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符# c! Y, `6 T. d% w( S8 @: w) T
  33. % m$ L: O6 ~6 c4 \
  34.       yOffset -= lineHeight;                // 更新y坐标
    0 d4 W- w) ~7 f; e
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置/ g0 {+ N1 W3 `! n, y
  36.       textData = currentLine;              // 将textData指向currentLine
    9 {6 d0 \$ l1 ^/ F0 Z( S7 t) Z
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度6 h, V+ s2 J% E+ m* j
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    ' N- V3 g2 A0 B# \# Y
  39. & E- E8 T3 M% U& g
  40.       if (lineIndex < numLines)0 v; X5 ?4 H2 @
  41.         lineOffset += 4;                   // 更新lineOffset$ r9 m1 i' s& {- i1 Q, _
  42.       ++lineIndex;                         // 递增行索引
    ' ?7 S3 P; d6 }; \
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据! M' `, L/ b. b& |  E3 r) i
  44.     }* `9 Z) F; G& _% _9 y6 k
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环+ _4 J2 f) d0 E1 A
  46.     glPopAttrib();                          // 恢复OpenGL属性状态/ P7 \  P- S; w4 v9 `# G( }
  47.   }
    3 n/ [" J' @( O
  48. }3 ~/ {  }* U; x" J# @! F
复制代码
' k4 d$ `& c  i6 [: g
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
6 E. y/ _" z" \" I& g7 h& D; X
6 K$ t: S1 T; e& N% h3 o8 O* mint xOffset,      字幕的x坐标
) z: r) x3 Q% h# w" vGLint yOffset,    字幕的y坐标3 [2 L2 J) P5 @. g
int numLines,     字幕的行数(较长的字幕为2,一般为1)
1 I& F# `+ [( t( `& `int lineOffset,   这个需要再研究' K# E+ Q% D  ~# W2 c
int lineHeight,   字体高度(或行高)
  \/ }/ y: k) Z7 R1 IGLuint displayListBase, 这个字体对应的base值
3 }6 d# e& t* V# F( ]char *text, ...         字符串, o/ ?, X1 A( N6 H/ T; E

6 \) t1 }' {  g/ w
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来- Y. D1 k2 j9 f$ C$ T) u
回复 支持 反对

使用道具 举报

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

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