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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑   }4 `( @/ V' h' e# q
( o3 y( I6 n" n' ]9 K9 N% f
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
/ e: g. D/ v( j6 J: {* N因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。& E/ q3 @9 S1 w# Z& i( R
https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
% W3 l& Z+ }' v5 `2 p1 P第1处$ A8 l: @) B+ T0 @. v7 A
  1. void sub_451474(char *a1, ...)
    8 ~3 D' O: X! s2 e& }' D
  2. {
    9 ^8 E: y. M% F/ y! i8 h, m
  3.   GLsizei v1; // eax
    - d) p. _: `9 ?( E- L! j( f
  4.   char lists; // [esp+4h] [ebp-800h]9 w' |9 u! C0 z
  5.   va_list va; // [esp+810h] [ebp+Ch]
    - ]' L3 }$ Y! z( _0 B5 u4 b, p

  6. 5 P8 P4 p' v6 |. U4 G/ t4 w
  7.   va_start(va, a1);
    & [; @/ i* d" s. z- l) L7 z
  8.   if ( a1 )& M. D4 \- k9 t1 [% g2 L
  9.   {
    7 g* g& a$ w$ r
  10.     vsprintf(&lists, a1, va);
    # v" H! w6 l. P) b4 j
  11.     glPushAttrib(0x20000u);
    / S  I1 f) F5 F, Y: u6 u* V* i" L0 W
  12.     glListBase(base);: K  q9 U' _& f! J3 a2 j* P' h
  13.     v1 = strlen(&lists);
    1 r" ~9 L( Z0 O1 V5 b: I6 L/ E
  14.     glCallLists(v1, 0x1401u, &lists);& K3 r2 p3 c7 N- y" L& |
  15.     glPopAttrib();5 i5 V) W2 m, c2 @5 D) U) a
  16.   }
    6 f+ U* j, f* L' H! a/ N9 g. H# y
  17. }
复制代码

$ o4 N7 O0 {. u" t/ h) ?
) T# c! q+ g. C7 z! D2 r  d
; I# F7 b9 }( O) a1 O* h第2处
( w" V) h  \% e6 P% {' L  o
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    + `# O$ n# e- Y2 j( }8 ^
  2. {
    : M/ L; [6 Y+ t* T0 c
  3.   int v4; // eax
    ) \- }* u+ h8 z/ e3 K- E
  4.   GLsizei v5; // eax( s3 E/ _  `" v  Q' E$ z* j: f! [
  5.   char lists; // [esp+4h] [ebp-800h]
    8 M# v0 k( l. o3 Y
  6.   va_list va; // [esp+81Ch] [ebp+18h]2 l2 C% e8 j. I$ |4 S4 w4 X
  7. & q7 b8 z6 F: T/ z# ~' i
  8.   va_start(va, a4);
    , M5 r1 K0 b: b" |
  9.   if ( a4 )
    ( `  N7 f8 F5 G8 I" e/ H( j  p: B
  10.   {) E8 O$ v% O' k! h4 k  u
  11.     sub_44F8A0(a3);/ ]  ?. d! v0 r5 n
  12.     v4 = sub_40BB44();+ A, D6 d, o) [" S6 N9 _
  13.     glRasterPos2i(x, v4 - a2);. e5 C) O1 G3 K
  14.     vsprintf(&lists, a4, va);
      z" d% k) W* i6 k
  15.     glPushAttrib(0x20000u);3 T1 m# |2 N6 D$ i% u  q7 c2 K
  16.     glListBase(base);" X: A6 e% q4 Y, E; E
  17.     v5 = strlen(&lists);/ e9 z2 p1 l; h: ?, N' B
  18.     glCallLists(v5, 0x1401u, &lists);
    8 s: x9 u/ O. c% l9 |$ q+ J5 L, r
  19.     glPopAttrib();
    ! Z. P4 q$ F; P: j( X8 J
  20.   }/ `; a* }3 X6 L3 e+ C
  21. }
复制代码

7 m9 h& `* P4 m' D* x( L0 j
. {" M6 ~) ~$ x; f; A8 f6 V, r7 Q/ d' \4 ]$ u" X
第3处
' m) z! n- V# T/ Z5 m. S7 t
  1. $ b1 [8 \$ g) ]+ x+ t; a
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)- N  M* o8 }! a2 q0 ~1 l# k6 R% s
  3. {
    * m$ t$ v  X8 h) P0 H
  4.   GLvoid *v7; // ST08_4* q/ ]9 N" G$ n6 d, G
  5.   GLsizei v8; // eax
    . E8 W5 @' Y+ `3 Q( k1 o3 i- m. W7 Z6 ?
  6.   int v9; // [esp+0h] [ebp-1018h]# u0 P4 s+ z, |4 ~5 M
  7.   char v10; // [esp+8h] [ebp-1010h]
    5 B3 r9 V: F9 H5 e  N$ H7 K
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]) v. N6 V/ B0 V- R9 a
  9.   char v12[5]; // [esp+1013h] [ebp-5h]6 \. S6 J* i! E1 ?& D; r
  10.   va_list va; // [esp+103Ch] [ebp+24h]
    / Z7 Q) f( x" Q1 h; Y# D+ W5 R0 @
  11. / w! ^# W: T9 q5 i- e
  12.   va_start(va, a7);2 i' g! |; C4 f- M; S) T7 Y
  13.   v9 = 1;
    ) j$ ]+ }4 h2 y4 q+ ?7 M4 h% j& w
  14.   if ( a7 )
    $ p. z" }4 V. U1 @  S
  15.   {  I5 Z3 ^, X" D* E4 M% D# s4 Q7 |
  16.     vsprintf(&v10, a7, va);6 J3 B& U: x5 K1 V# x+ O1 B3 y( T
  17.     glPushAttrib(0x20000u);
    . V: H; ^5 m: {" c1 M
  18.     glListBase(base);3 m, ~3 j; x6 f: Z) W
  19.     lists = &v10;/ V: t# A) ^4 k- P
  20.     do, `% _4 Y/ o6 r( h. r3 Y
  21.     {# `! B6 U" b1 M1 h* @3 w0 ]
  22.       *(_DWORD *)&v12[1] = lists;
    7 S- ?4 V% Y0 e. e& {7 W
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )
    . f0 i% h/ q* X( b* S
  24.         ++*(_DWORD *)&v12[1];" p4 W$ e3 W* f- J1 l8 w4 o  X+ T9 E
  25.       v12[0] = **(_BYTE **)&v12[1];
    & ^% p6 D, z( r; H* b' C, `  }' e
  26.       **(_BYTE **)&v12[1] = 0;
    & A! {$ [8 z$ |( x: s9 A
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    1 f  v$ M/ F: D" h
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    7 T% Y) Y2 ~3 p
  29.       y -= a5;
    ) O5 r; {' e4 F( ~" L- t) H% \
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);! S; r/ g6 Q: q# N, I
  31.       v7 = lists;
    % m$ T- s, g" s( C" n1 N
  32.       v8 = strlen((const char *)lists);
    , x1 T) z8 Q" K+ v
  33.       glCallLists(v8, 0x1401u, v7);
    # a+ R& [, u5 U- T9 x2 T3 _
  34.       if ( v9 < a3 ). f( ~. n4 \0 c; @6 B
  35.         a4 += 4;
    3 R1 n, t4 g3 [: @
  36.       ++v9;
    , F: o; H7 ?0 `  A6 A8 {3 e6 I
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
    ) x9 g6 g7 q7 E9 V/ m6 O* \
  38.     }: n7 _6 ~/ _2 y7 X
  39.     while ( v12[0] );
    4 O9 F  C  `9 z, y
  40.     glPopAttrib();! h' `/ I- Y2 p" ]# g- x
  41.   }/ j5 n0 A; }8 T2 {$ _
  42. }3 V) J/ \  S9 g1 B% O# }# w
复制代码

1 `! R2 H7 _& B& @* j调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810* h: c$ a  O8 u$ c

! D3 C5 b5 D" h
  1. .text:004512B1 52                                         push    edx             ; char *. K( |1 B0 }. a* t# ^" `
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    8 t8 m, G1 L9 P8 u
  3. .text:004512B5 50                                         push    eax             ; base, }4 J- J) S# I' r
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]5 `, y- F9 ]0 y5 s6 i+ a
  5. .text:004512B9 51                                         push    ecx             ; int
    3 q  O0 ?: u  @0 f& d
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]
    : y5 J( s  F0 l0 L( L
  7. .text:004512BD 52                                         push    edx             ; int8 {- k4 t' u( u
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]8 t+ E' h& {4 b& n7 |2 G% O
  9. .text:004512C1 50                                         push    eax             ; int2 O& H2 L- G. B
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    7 `/ g' p  V' }( ?% B3 `6 s: t, y
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]: y: V9 V, c" L) K
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    * X( [& c$ d& S: K4 L: N# j! l
  13. .text:004512CB 51                                         push    ecx             ; y
    ( R. h2 Q' u! r  e' W
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]- r. q: i( w- J
  15. .text:004512CF 52                                         push    edx             ; int" Y- l. g, x' G0 B3 k6 }7 r: |
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
  H! I, g4 [* E& b% l
chatGPT整理过之后,如下
+ \1 b  r7 D/ J8 }" K6 @) A6 f
% v, [2 f0 |  t
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    * A$ P& S! L- u+ i% e( L
  2. {7 t+ o# y0 M/ E# H- ^! w% P
  3.   GLvoid *textData;         // 存储字符数据的指针
    # L8 a1 i  c1 p! H; e
  4.   GLsizei textLength;       // 字符数据的长度% j8 b- L: f9 j  Q( X% V
  5.   int lineIndex;            // 行索引" u. K5 U2 k7 a
  6.   char formattedText[5];    // 存储格式化后的字符数据
    . r! Z/ X$ T, o3 ]& n, `' b2 P
  7.   GLvoid *currentLine;      // 当前行的字符数据指针3 W2 W$ `9 w: L
  8.   char buffer[5];           // 字符数据缓冲区
    6 q$ L! {4 P9 O( M' Y* s
  9.   va_list args;             // 变长参数列表( V# v) H7 K1 ]: w; q8 @8 j
  10. : o; I- ?* E2 G: k* S$ v6 i* |1 j
  11.   va_start(args, text);     // 初始化变长参数列表
    % @1 Z3 Y# f! v. |2 H6 p- a/ }
  12.   lineIndex = 1;            // 初始化行索引为1( K) @0 p2 u8 {3 \7 R  m5 X
  13. % R6 \5 L5 U0 o, w, U$ T- P# d
  14.   if (text)                 // 如果文本不为空
    / \/ ~0 @1 n; x1 y
  15.   {: R- }( \, ^& s
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中
    2 w# y  V/ |( B# M5 ]0 @
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态) ^# _" `$ S9 ~6 y
  18.     glListBase(displayListBase);          // 设置显示列表的基础值
    & S- c4 x: b  V/ d2 i
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
    ) L" l3 b5 ]: u, C+ U

  20. 9 h5 ~  J: T( j0 q/ c3 _0 _. D
  21.     do+ U1 D. J# a/ _
  22.     {/ a5 ?0 x& i" E* [- a$ G
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素( ^) B: z: e! B8 E
  24. 5 D' y! Y4 u+ S
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束8 M+ n' `* U* b, z" [- ]
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
      q, I, r$ n$ w* p. L) m

  27. 7 J( G# \4 ]$ X. h. K- ^/ T5 [- W
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素( W$ M& S, m' ?  p. ]0 Q; [
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符  |: A, M. |% A6 R$ J- e
  30. & C% z! n, @7 c0 Y  ]% n9 N
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    2 l" X6 X6 w1 S1 V4 h- E
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    - z, q+ y9 K9 G4 h* }7 s

  33. 3 o6 z$ U# x: R# c1 q+ w
  34.       yOffset -= lineHeight;                // 更新y坐标5 W+ @# H3 l* g; l
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置0 ?1 ?9 r0 D8 D4 ]" h- I$ N4 X, B3 o
  36.       textData = currentLine;              // 将textData指向currentLine# j# t) _& m! `
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度# q% L& t9 n0 H) Y* C
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    ) C. v7 N9 s+ d4 _& M  j5 [/ S
  39. 2 a2 K: J& c) I0 M( L
  40.       if (lineIndex < numLines)
    3 h6 I6 V+ u- y0 O$ T
  41.         lineOffset += 4;                   // 更新lineOffset% m3 Y2 |' \9 k- n# ?9 @! q
  42.       ++lineIndex;                         // 递增行索引
    3 R2 x' i  _$ f+ U% j7 c
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据0 G! S, @2 Q% O- \1 N; j6 V& X
  44.     }7 u( r3 T1 E$ q3 O- l2 P
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环# j7 H" Q. Q! A' k: O$ v) y- y  V; ?
  46.     glPopAttrib();                          // 恢复OpenGL属性状态0 ]( D" `: l: b% c+ I2 G  i
  47.   }6 s! P, A) U7 c4 R
  48. }2 C$ ^5 q2 t2 Y4 G! V
复制代码
/ ]7 I% E8 Z7 \- O
含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
9 w3 k2 @8 G9 J8 N3 p- n4 a4 p/ S# a) c
int xOffset,      字幕的x坐标% a. h7 _( _+ J9 A  A) y1 d0 U  g& `
GLint yOffset,    字幕的y坐标
6 Z5 P( u) v' S. P$ d4 Yint numLines,     字幕的行数(较长的字幕为2,一般为1)) e/ ]9 R6 J( n& z9 q
int lineOffset,   这个需要再研究
" g+ r0 u, J+ ?9 u+ u7 E2 M8 Uint lineHeight,   字体高度(或行高)5 c' H: i5 ^0 V: q
GLuint displayListBase, 这个字体对应的base值
8 C6 X9 q4 d& X9 d7 pchar *text, ...         字符串
- o2 i: y" u8 w# J% N$ i5 J
5 e* |& _5 q0 @! a  I7 G
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
" j7 A/ [/ J' d* u: u/ f
回复 支持 反对

使用道具 举报

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

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