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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
. V2 {. c4 b6 l  Z5 H" H( ~4 a
" w! ?0 M- g4 w4 e* R3 s  A1 z这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
  p" ?# f; Y& d3 o8 L! K  K因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
1 l, a/ q" B6 y. I- r$ ihttps://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
$ W' M8 Z6 `+ C9 E7 N) k第1处
# d/ Z8 C/ D: D9 J# R
  1. void sub_451474(char *a1, ...)" x  J& h; P# R, G8 I
  2. {
    # i8 c/ d1 Z6 Z" Z) Y# R
  3.   GLsizei v1; // eax
    ! i$ ~  b& D9 I! Y. |. k
  4.   char lists; // [esp+4h] [ebp-800h]- `$ t) f% c, Z* x4 a$ Y9 q& L
  5.   va_list va; // [esp+810h] [ebp+Ch]
    - ?! ^  z5 ?* \* c  Q9 x
  6. . o/ I- l* R/ O- `# [8 @; [5 M4 G
  7.   va_start(va, a1);
    / S7 c) L5 Q' x) _- u2 c" O
  8.   if ( a1 )
    9 u6 o6 I# I6 j/ C
  9.   {- O- P$ y% o: @
  10.     vsprintf(&lists, a1, va);
    # j2 g9 r% v: S/ v  T6 |, ~
  11.     glPushAttrib(0x20000u);
      X3 ?) }) O* u# c! Q/ ?
  12.     glListBase(base);
    2 m4 N# g/ O  ?& A4 \9 \% C
  13.     v1 = strlen(&lists);2 W" `! K- c  Y9 p' y: ~, v
  14.     glCallLists(v1, 0x1401u, &lists);
    # }* E( X8 r2 o' N" E
  15.     glPopAttrib();) l; V& {  o. i' k
  16.   }
    $ q8 u0 X# k  c5 }% o- k0 J
  17. }
复制代码
% O2 s3 ?7 L3 f9 }' Z* D# j/ Y' r

/ T9 S) R! s! r( v0 L0 ?7 c
2 e( a! Z, I) ~! C8 U( ~第2处
8 t6 T7 ~, O: F
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)6 Q4 ~0 w1 C/ m- l% h
  2. {2 b% q( f6 D" R  ~1 S. W
  3.   int v4; // eax0 {( x4 {6 {6 N% B
  4.   GLsizei v5; // eax2 o, u" f9 a. C- l
  5.   char lists; // [esp+4h] [ebp-800h]! A3 \+ K$ B1 o) p5 ~8 W
  6.   va_list va; // [esp+81Ch] [ebp+18h]
    / b9 `2 A+ ^) L: |+ u

  7. 1 k4 K, y0 r* u  m
  8.   va_start(va, a4);
    ; m* h3 ^6 v& b: V. T, |
  9.   if ( a4 )
    0 s* D8 M; ]. V
  10.   {
    ( Y* i6 S6 o3 Y2 Y
  11.     sub_44F8A0(a3);% _3 s8 ^7 L" c, A" }
  12.     v4 = sub_40BB44();& `  a2 G( I8 x, n$ {
  13.     glRasterPos2i(x, v4 - a2);7 A% k: l* [, q6 @4 T
  14.     vsprintf(&lists, a4, va);* J/ ~' H4 T/ q. o2 d) V
  15.     glPushAttrib(0x20000u);
    ' J0 k+ C( S) Y+ G7 S0 [2 \
  16.     glListBase(base);6 B4 O1 F2 B7 r5 e0 t' h
  17.     v5 = strlen(&lists);" p' l* n0 E7 p( r& w5 E
  18.     glCallLists(v5, 0x1401u, &lists);8 ~- l1 h& {, G* [7 ?
  19.     glPopAttrib();
    : G. d( D% u& \
  20.   }9 |' U: x; I/ Z. y# f( s
  21. }
复制代码
+ }/ R) I' [- O1 ^, y+ U- [0 w8 }

4 E  p0 ~3 s5 \: Y7 f3 F7 H$ H% M# H- m* `" n) M$ \
第3处
) y9 A" T9 M* J5 u+ S, D
  1. / }; d4 {" |# w8 X' Y, a% Q
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)9 K( h: c6 W9 c6 q5 G! G
  3. {- ]4 G, T+ g, m+ C; Z- W
  4.   GLvoid *v7; // ST08_4/ p4 s( h8 I9 O- i7 C3 c( i
  5.   GLsizei v8; // eax% ?7 `$ S( s  w) f
  6.   int v9; // [esp+0h] [ebp-1018h]+ ?& _0 Y. v& C# ?7 S
  7.   char v10; // [esp+8h] [ebp-1010h]
    9 q4 M' K; _' D' y
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    , p6 y, K' c3 N) g3 F
  9.   char v12[5]; // [esp+1013h] [ebp-5h]4 N4 P! J3 ?$ H
  10.   va_list va; // [esp+103Ch] [ebp+24h]7 C  b4 w; A/ [! J

  11. $ q  ~( f2 J$ X
  12.   va_start(va, a7);) L' P! l" {2 b$ P5 z# m2 S3 _- b
  13.   v9 = 1;
    : ~4 y+ c3 h' ]$ m: r) t8 O% I
  14.   if ( a7 )
    + j; U# ~% B" H0 a" N" q" d! O
  15.   {; k3 @( D2 o6 ]" l6 M( j
  16.     vsprintf(&v10, a7, va);' v  B2 v, C# e; S  K; ?  G: m
  17.     glPushAttrib(0x20000u);
    2 _: J! s( M9 a
  18.     glListBase(base);) K& H* m8 @, u9 [' |0 I
  19.     lists = &v10;
    + P4 f9 n% g' \( T4 m# g* `
  20.     do
    / l8 d& c! Z7 E- H9 H
  21.     {
    / V/ O9 h: Z- A, H* r# U! o
  22.       *(_DWORD *)&v12[1] = lists;
    8 D: A- L0 u3 W1 S
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )4 h4 n6 k0 d: s6 c: ^3 N3 V
  24.         ++*(_DWORD *)&v12[1];
    # S6 F% \" i0 y9 ^: j6 i; [
  25.       v12[0] = **(_BYTE **)&v12[1];  S9 Y  S0 L  J& R+ ~8 z- \  q
  26.       **(_BYTE **)&v12[1] = 0;' B7 _2 W9 S% Z6 }; h- F
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )* A* i9 i0 `$ b5 [( {: N
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    ! F  u( P! t: j0 g2 Q" s2 b
  29.       y -= a5;
    + \, _* z- n$ d2 g8 P
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);; [2 y* }" B8 V+ A% m
  31.       v7 = lists;2 o/ l) K! N( S: l" `4 r& L
  32.       v8 = strlen((const char *)lists);
    : o! O  f+ ^2 A( z. }  g
  33.       glCallLists(v8, 0x1401u, v7);
    - o( V, R( D9 F. `
  34.       if ( v9 < a3 )+ S, S5 k/ g% T, q" D4 d- }3 C: ~
  35.         a4 += 4;9 i4 `' ~9 I6 W9 w
  36.       ++v9;
    # m" J  k* d  ^/ C) F3 b
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);2 t3 i* N2 v1 v* e0 ?, N/ E
  38.     }
    & J- g* g% g3 `
  39.     while ( v12[0] );( Z5 I* e, o2 J7 J* N- g  p
  40.     glPopAttrib();* u/ e( w2 I2 o. w0 n: c
  41.   }
    2 U5 ?" @2 D$ B' ]# f
  42. }
    3 n+ t* L/ C; K& F3 d+ k; {* Y
复制代码
3 a, l4 @8 C! S( e" G. i9 T- Q0 Y& b. l
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
2 y( q. f# J9 e( z. q, i3 G$ Z% V% ?) J4 Q7 _' e/ j9 ]9 D. S
  1. .text:004512B1 52                                         push    edx             ; char *$ Q3 g- b+ g6 w: M
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]5 G7 X# R2 L. P( f9 J7 }
  3. .text:004512B5 50                                         push    eax             ; base
    / Q5 q% o2 A/ {) ^% \+ I
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
      D( C( t2 d& _5 K* o6 ]+ b
  5. .text:004512B9 51                                         push    ecx             ; int
    8 X  l$ e5 v1 n: I0 e* F, I$ X
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]# x6 T# Y1 Z  \1 R) n+ f, n) Q
  7. .text:004512BD 52                                         push    edx             ; int+ w# O; S" [: I" o6 q
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]& {! s9 f; o1 d. a
  9. .text:004512C1 50                                         push    eax             ; int
    % N* b2 H- ~4 j( R& w7 N
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    . Q" C# X" H1 R
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    0 X1 R6 @% `" c; B- ^* v; u4 D% G
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    . i* @. k# g) y
  13. .text:004512CB 51                                         push    ecx             ; y
    ) T2 I0 n; R& w: ~& F# ^; X4 L, L
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]% e; ^' [4 s7 q
  15. .text:004512CF 52                                         push    edx             ; int9 C4 y- {: h# L+ Z) e# i; E
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码

1 A9 A# _+ _0 w1 c% xchatGPT整理过之后,如下  z6 O( e  w4 @  B; |

' s& V2 O, F/ d$ |: @
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)  B) e% B/ b' o4 N( U. l0 T7 P9 b
  2. {
    3 j$ L) a) [6 I8 M2 w, ?
  3.   GLvoid *textData;         // 存储字符数据的指针
    & m( e2 V& T; X  O. @5 `3 a
  4.   GLsizei textLength;       // 字符数据的长度
    3 E( O. k  K# i1 T5 K0 }6 i2 O  [4 Z* B
  5.   int lineIndex;            // 行索引, S& W# n) E, ]( r5 S  }
  6.   char formattedText[5];    // 存储格式化后的字符数据
    ; ?3 F1 Q! Q) m7 i5 w
  7.   GLvoid *currentLine;      // 当前行的字符数据指针9 K5 R8 y+ K+ y( ?, I( u$ _3 @7 B
  8.   char buffer[5];           // 字符数据缓冲区
    0 S" T; w  ^( Q( g% u' P
  9.   va_list args;             // 变长参数列表% a( D" V6 Q: H. M4 d
  10. " Z( S, z0 ]7 t3 L( T* L
  11.   va_start(args, text);     // 初始化变长参数列表: M" o: o5 Z- |5 H5 K0 \. q
  12.   lineIndex = 1;            // 初始化行索引为1
    + K  e* }; G, b' V5 l& i
  13. 2 \$ t+ P1 k; e+ U3 B: {
  14.   if (text)                 // 如果文本不为空( H/ ^. d/ K% h* r8 F
  15.   {5 X7 t1 S8 M1 b; W: C4 E+ i
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中, N; p1 S/ x" n9 s/ c% t
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    . b% [" A; X& p/ M6 q
  18.     glListBase(displayListBase);          // 设置显示列表的基础值; O' \& }" x0 R- P; z4 \
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置5 X9 U1 T, @9 r

  20. 1 a' M& v2 L  w- K
  21.     do& m' f  R2 p/ V" y; K8 R
  22.     {2 ]8 Q8 d4 @/ Q3 w) A' ?2 |  @
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素) A9 o; R7 n: U# ~. @' q
  24. 6 d. g) B5 H0 H& b6 j; ^$ b
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
    " }5 r. h" @, ^  `
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素1 D) o6 \3 i6 R0 m1 n: C

  27. 1 D8 e1 |8 @. X" }6 l4 \
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素/ H5 T4 j1 D- V  s/ c/ \
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符! @; U# E0 M( P" S7 t$ C
  30. * i% H% l' n6 T" p& _& o4 t- F$ K, [
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    ' E) v" K0 p7 t" N6 A
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    3 u" X5 ]. s" M$ s# _( e9 }
  33. / X; @3 s8 v( {4 R3 {
  34.       yOffset -= lineHeight;                // 更新y坐标
    , b4 p  g) X$ Y- S0 J- U
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    , i8 h& O8 R2 f, l4 b
  36.       textData = currentLine;              // 将textData指向currentLine" V" q1 S; c7 m2 `7 {
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度  H4 R" |) h4 k4 H$ J) b
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    2 u8 V' z$ x9 b8 Y. B1 P
  39. 0 G' Z: {/ U9 k5 s4 b+ p. N
  40.       if (lineIndex < numLines)
    - F! p$ O6 w/ q+ b  j3 }
  41.         lineOffset += 4;                   // 更新lineOffset
    " B$ h$ `4 ~" u% {& \$ g
  42.       ++lineIndex;                         // 递增行索引0 f' l+ g. s" h' A
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据/ J2 B# N# X' z
  44.     }% I, C' }* Y& _9 p; q- \
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环+ D, C" P) Q% `7 x! B% \) C
  46.     glPopAttrib();                          // 恢复OpenGL属性状态
    5 K' h; c0 ?! j/ `' Z1 J
  47.   }$ u' G0 Z3 W6 H
  48. }0 E) I2 O" K% W
复制代码
6 r/ K; y) J" M& F
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
" C4 t# P" f, d- ?+ [9 E7 T6 r
- a2 N; Y, `( u8 Tint xOffset,      字幕的x坐标
/ f1 t# Z3 d& M9 h/ Y1 HGLint yOffset,    字幕的y坐标
% k$ b: W& }7 J# W$ mint numLines,     字幕的行数(较长的字幕为2,一般为1)# z' Z7 E) F) h0 \- Q
int lineOffset,   这个需要再研究: b& n/ C5 w% K& Y
int lineHeight,   字体高度(或行高)
! X# \0 _) R7 d( y. {8 t+ a* x8 N/ ~5 mGLuint displayListBase, 这个字体对应的base值
) \. t! E# b% j' zchar *text, ...         字符串" t. d/ ^6 [" |: p' |& G

3 o. l# ]. w) ]
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
+ Z! _- w% C' c# G0 b( h2 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日,是全球华人共同的冒险解谜类游戏家园。我们致力于提供各类冒险游戏资讯供大家学习交流。本站所有资源均不用于商业用途。

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