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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
1 [8 x5 a% ?: P
) l& P# u$ i; {9 n! _8 I4 X这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
5 A5 x% Y5 Z, L6 F4 h因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
8 I' H7 n6 b- a  Z( Xhttps://www.chinaavg.com/forum.php?mod=viewthread&tid=1540816 V3 ~* M$ I. b
第1处
  z2 A; S  \. f2 T( i2 u% L! ?
  1. void sub_451474(char *a1, ...)! X# [+ R& }  H
  2. {
    ' W: C: h$ u0 l* [1 M
  3.   GLsizei v1; // eax/ b$ @7 R& r+ {0 m* L$ o2 I
  4.   char lists; // [esp+4h] [ebp-800h]
    - A7 J, \/ b( F- H5 P6 w
  5.   va_list va; // [esp+810h] [ebp+Ch]& ]% S0 D' `8 H& H% j% I9 C& Y7 M

  6. 8 J3 [  t. c; M: }& j8 ]" X' X+ ^
  7.   va_start(va, a1);, X/ ?& J/ [# k8 o! Y3 e) y
  8.   if ( a1 )
    1 o5 t; u; `' f4 H, Y/ P+ B& F
  9.   {
    ' _& C* [/ @" r) _9 l* W
  10.     vsprintf(&lists, a1, va);. j3 l; O4 v, L7 ~+ b
  11.     glPushAttrib(0x20000u);% N2 Q$ L" D( p, @$ o* d+ W
  12.     glListBase(base);
    ! J; P1 ?& C+ N0 F6 I$ y. O
  13.     v1 = strlen(&lists);1 C* K  I: f2 c& T- j1 H
  14.     glCallLists(v1, 0x1401u, &lists);
    9 `* B' n- E# ]
  15.     glPopAttrib();" [9 B9 u3 }; a( R% J# H1 H
  16.   }7 s& D4 E/ q; d/ c
  17. }
复制代码

# A  w1 L  T5 m% z( v; d
" Q6 c& f+ K& I6 I# }8 j2 b
& R# w$ n: o( `9 k  C! f# j第2处: U9 P% e* B" J7 I* s* B
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)( O: n1 o- a3 `( c" m- }% j5 x
  2. {6 ^$ w/ V) n3 t) S
  3.   int v4; // eax) U' d' [* g1 r. Q# l
  4.   GLsizei v5; // eax2 T- l' P1 ~7 j3 t. K
  5.   char lists; // [esp+4h] [ebp-800h]
    & s8 i7 _7 D$ V5 N
  6.   va_list va; // [esp+81Ch] [ebp+18h]0 x& t$ ~0 v- q' s9 o" V

  7. 4 e& z! x8 w. Q7 h5 U' p
  8.   va_start(va, a4);
    : s6 ]9 X6 o1 _8 ~3 H
  9.   if ( a4 )
    ) J7 _3 u# M, _: m: ~% y; |; c: H3 e6 j
  10.   {) t2 z3 p$ i# \4 E/ {( g( N
  11.     sub_44F8A0(a3);- n, S- N6 H) V/ N
  12.     v4 = sub_40BB44();
    + \. e% V- J) ^% `+ E  G- \' @7 A: |
  13.     glRasterPos2i(x, v4 - a2);" X0 d( @& z! B5 E+ y
  14.     vsprintf(&lists, a4, va);9 y0 {: d" k% P2 L6 l) V; n3 I
  15.     glPushAttrib(0x20000u);
    $ C0 N8 x- Q% |# b6 C- m
  16.     glListBase(base);
    4 b! a: g0 a2 W
  17.     v5 = strlen(&lists);
    * C" n1 e! |+ d. N$ X- ]8 ~
  18.     glCallLists(v5, 0x1401u, &lists);
    & s/ R8 O$ e6 }6 f
  19.     glPopAttrib();" N) ?' f5 p6 l; `3 j( W
  20.   }6 P/ F8 ?" w& _3 f
  21. }
复制代码
2 `1 |2 \: z+ U  n' g! P8 ?
* _' |3 s7 S: N; Y$ O' Z  L

1 e5 m9 m0 F7 q2 a$ o第3处+ E0 W5 S& C6 |6 r: V, m
  1. : c6 g8 X$ e+ g0 @  I6 G$ [
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)6 _' P8 V' W& E+ X  M4 Z* C% M
  3. {# A( g% c! t% K1 I* S
  4.   GLvoid *v7; // ST08_4  @9 f6 _8 l1 n0 I$ T1 O3 F- n7 |
  5.   GLsizei v8; // eax4 a! C  {' t. t" c5 l
  6.   int v9; // [esp+0h] [ebp-1018h]' C3 {& G4 ~1 ~5 _4 k
  7.   char v10; // [esp+8h] [ebp-1010h]/ W3 i7 @& x# x2 z* C% D. J
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    - T9 U# q2 {( n; h7 Q
  9.   char v12[5]; // [esp+1013h] [ebp-5h]
    " B; `4 }# e3 D! Q, g9 ~( Z/ j
  10.   va_list va; // [esp+103Ch] [ebp+24h]+ F" G6 J! K8 m! U2 |+ U

  11. ( g# b* f- [8 k% e
  12.   va_start(va, a7);2 o  g; `9 |" f0 Q  c
  13.   v9 = 1;! E8 H6 o& F$ O' W5 W1 F
  14.   if ( a7 )
    & e2 i0 W. U) e% [) N) F7 [
  15.   {
    3 P. C% z, Z) t4 d" c# ~- g$ a# a
  16.     vsprintf(&v10, a7, va);
    6 K% F9 E( P6 ~9 O, [" `6 j, A
  17.     glPushAttrib(0x20000u);
    2 f9 [$ h! E- {" U# f+ o
  18.     glListBase(base);& B3 h% w* U! Q
  19.     lists = &v10;
    ( v4 U2 q& M. E
  20.     do" Q. i/ ]! A1 m
  21.     {9 c: z$ E- \* O# C" O
  22.       *(_DWORD *)&v12[1] = lists;
    ) w# N3 _9 [4 B& K' e! `
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )
    ( H, `7 a* u3 o& g4 h
  24.         ++*(_DWORD *)&v12[1];' G) q" U( z, @& ~5 U
  25.       v12[0] = **(_BYTE **)&v12[1];' Z6 c; Z7 i4 W
  26.       **(_BYTE **)&v12[1] = 0;
    ) m* I" K# y. w# J/ D8 A" s( v
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    + H) W7 `% k+ P" l/ ]2 Y
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;6 g2 [% ]2 A- ^4 B, E
  29.       y -= a5;' v$ i: k/ P% N7 s# k' r. q" Y; X  w
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    3 }9 Z. x+ B( Y9 q, l, r
  31.       v7 = lists;4 @8 {' M! y# `& v: G
  32.       v8 = strlen((const char *)lists);
    & q  C: G3 ^5 o. v8 l0 B
  33.       glCallLists(v8, 0x1401u, v7);
    3 o9 B& s4 d1 o
  34.       if ( v9 < a3 )
    * r3 s2 y- Y" s3 }
  35.         a4 += 4;9 V& j# r) ]% w: T" Z+ j9 c- H
  36.       ++v9;& C5 m6 N5 m% `+ T4 W
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);7 |6 {* I8 F5 l  o
  38.     }
    3 ?7 b. e/ ?: O
  39.     while ( v12[0] );
    7 j, r$ Q. s- y, u3 o
  40.     glPopAttrib();
    ( y; a" z* S4 A+ m
  41.   }8 ~* Q" O) x  R# y/ l8 K6 X
  42. }6 y. @) r% {* y3 ?: u
复制代码

- y3 S) m' [7 W! ^调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
( y1 Z9 ]% s( O7 X) f8 Q6 t+ M- Q
  1. .text:004512B1 52                                         push    edx             ; char *2 ?  t/ x) Y- ]/ ~; O" m: ?
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]) w& p" z. }% A6 a; [9 r
  3. .text:004512B5 50                                         push    eax             ; base6 I0 `( R7 w1 C' d& t& C* c) T, g
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]( R% e1 _  o: ~9 N4 A
  5. .text:004512B9 51                                         push    ecx             ; int
    + o# }% H/ q3 `9 [
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]
    ! l3 _1 \# I6 s
  7. .text:004512BD 52                                         push    edx             ; int
    . [+ y, j0 H: z) Q( o+ M4 Q  o" U) X
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]! Q& k+ f0 J4 x; ~
  9. .text:004512C1 50                                         push    eax             ; int+ A. J7 p: @8 {$ e% r: _
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    " @8 ]" E1 B% j* q: Z
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    * P: G8 X; t1 r/ h, D2 m* g
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]9 _; t1 D: v! ?; ~0 J; G( _/ ?
  13. .text:004512CB 51                                         push    ecx             ; y
    4 r+ P% F% E/ b
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    * s1 f0 K7 ^7 K  {, s5 M
  15. .text:004512CF 52                                         push    edx             ; int& G. W" p9 ^, p# {$ t' _7 t: K" z
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码

! p: C. ^& u: |; a% i$ i7 p$ IchatGPT整理过之后,如下
2 D6 s, E1 o/ g' V6 E- m. E4 [& V: `% N5 x1 s% F9 w
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    * g# f# |) l& B4 S2 P; Z# m- \
  2. {) N4 l  y' X; k) r
  3.   GLvoid *textData;         // 存储字符数据的指针
    2 x% G7 G' |$ k) Q0 f  _
  4.   GLsizei textLength;       // 字符数据的长度
    + B# ~5 z% ^( a' Y. W3 U  |9 [" }7 K
  5.   int lineIndex;            // 行索引/ Q( b. X# O' }( V7 s
  6.   char formattedText[5];    // 存储格式化后的字符数据
    , Q  w8 X! n/ e. ^
  7.   GLvoid *currentLine;      // 当前行的字符数据指针
    ; x( a3 ?0 @; t& R: h0 w7 e% l
  8.   char buffer[5];           // 字符数据缓冲区
    $ n  A& Z, W  H; B( j
  9.   va_list args;             // 变长参数列表( [0 i( L+ L* i# v; r$ n! [. o
  10. 0 S" c( U, l  m8 r; u1 ~! S/ L* U
  11.   va_start(args, text);     // 初始化变长参数列表
    8 o2 Q) [/ D6 R+ u& W6 {' d3 D
  12.   lineIndex = 1;            // 初始化行索引为1
    7 k  b9 k3 d. l4 z) Y
  13. & u$ o  m& E$ K, W7 ]5 W5 A) g; M" i
  14.   if (text)                 // 如果文本不为空
    8 ]7 r+ [+ ^, V; {
  15.   {/ Q& `7 e# W3 N. u6 h# V
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中; W* v; a8 w. w4 |" a* J1 O8 b
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态# S# M+ e  O; s4 T" w. g8 e
  18.     glListBase(displayListBase);          // 设置显示列表的基础值6 z) t0 e! A6 b2 m  O
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
    9 |+ ~# h2 u$ d- K
  20. " w7 G6 g( U' O# i3 k2 H
  21.     do7 Z, P. u, y" m/ ^6 R
  22.     {
    ' l9 \$ w/ c6 [& [1 {( t3 _
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素9 m( L$ u  M0 `6 N8 {& T
  24. : W1 y" L6 M* Y1 Z3 U
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束7 O* n  A- ?3 ?) s6 A5 S; {5 ~3 n# u
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    0 S% [2 L: |' ?: F
  27. 5 S4 {; w8 a& _$ J0 a8 W
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    6 B0 p) `0 D- f$ _7 r) k# q
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符
    3 X! t6 I+ a7 n" q0 c
  30. 4 G6 y# g, W; p  z" P
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    ) {9 Y0 u* \& `- x" t2 T
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    & P6 f! J; S& T7 m1 ~6 K
  33. $ j: S; t6 ?% ]) w5 \
  34.       yOffset -= lineHeight;                // 更新y坐标$ f5 I4 p& L5 k* V
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置
    4 w$ D' s' u& O/ V" a
  36.       textData = currentLine;              // 将textData指向currentLine& o1 m- M" |3 |
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    % A5 C4 d3 Q( E% i# P. v
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表& ^8 p8 I2 X5 g" \# z! d: H- _
  39. 7 c7 P( @7 {6 [+ k+ `
  40.       if (lineIndex < numLines)0 _+ _- X- U" R& k& X9 O' w# T
  41.         lineOffset += 4;                   // 更新lineOffset* g4 L3 c( A# M
  42.       ++lineIndex;                         // 递增行索引# e0 Z8 f4 X2 N7 w
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据' G1 F% s' b8 h8 E/ l
  44.     }
    * I+ |0 b; I2 v3 G( t
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    2 ?$ V0 _1 G/ R/ ~( T
  46.     glPopAttrib();                          // 恢复OpenGL属性状态6 I" @& A3 J6 @. I
  47.   }
    / d9 ?# y9 k9 F
  48. }
    % Y" q! ]- S! l- [: t! f
复制代码
$ ]6 g+ k0 U* f3 F# [6 s
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
6 T" |; {2 E- U% _$ _# R+ Z0 Q/ U9 c$ P# I7 O6 l
int xOffset,      字幕的x坐标
7 D- s2 I, U. j9 S$ x0 U3 DGLint yOffset,    字幕的y坐标
7 q) ~9 L& E7 R9 J( Bint numLines,     字幕的行数(较长的字幕为2,一般为1)
8 c$ i9 X8 j8 v2 Yint lineOffset,   这个需要再研究
; M0 ^4 `9 U* K! J2 Xint lineHeight,   字体高度(或行高)3 {8 ~0 E" B% ]
GLuint displayListBase, 这个字体对应的base值
' t1 F1 k, W: u1 @/ Tchar *text, ...         字符串  J' h9 K4 q3 b! w  Z1 U

' r$ \. V" ^/ S9 N
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来; n8 z8 \' I, l; f* i/ z. V
回复 支持 反对

使用道具 举报

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

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