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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑
+ T# J' [7 B( k5 F# b4 u: f' i6 T; c7 S" h  M0 J- G1 x, v
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
+ j# _* l8 U; K, Q0 M5 y' \0 b, `( ?因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
- T# V6 O9 S- e6 b1 T( d. Z2 Dhttps://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
' Q1 z+ J; j5 j) v4 G4 s. P第1处% ^1 N) I( B' r. D
  1. void sub_451474(char *a1, ...)% J8 \8 h( Q& V
  2. {" R' y0 W. q- f* z, u2 _" \
  3.   GLsizei v1; // eax
    ' X" N2 t' M$ v: Z
  4.   char lists; // [esp+4h] [ebp-800h]8 C8 m+ a; X0 o2 X* j" n- J$ t
  5.   va_list va; // [esp+810h] [ebp+Ch]
    & @4 N3 @1 X: [! v- ~. e; e+ c0 ^

  6. ) A4 F+ d5 h+ b' s
  7.   va_start(va, a1);, O, ]0 E* k7 U0 |6 H/ M
  8.   if ( a1 )
    ( a. Y- |/ I5 }3 m/ Y6 _7 N
  9.   {
    $ E" I- E2 \4 K4 ~7 q
  10.     vsprintf(&lists, a1, va);
    ( V% w+ N5 H# D- a$ |  |3 e
  11.     glPushAttrib(0x20000u);$ |7 m, r9 \' [1 d5 n. g# R
  12.     glListBase(base);
    1 X8 @0 E$ f7 m/ c9 z& \
  13.     v1 = strlen(&lists);$ s) n$ z; Q" p4 ~. e- f
  14.     glCallLists(v1, 0x1401u, &lists);
    / v7 j9 b' X9 @  S+ y& {
  15.     glPopAttrib();
    ( ?. B  n, p* k
  16.   }4 G/ V6 p! F; R
  17. }
复制代码

) `0 u! C: J  Q1 L- N) X5 s1 F; j$ V0 p0 I- J, v
) ]' w) p% |4 P: e6 e) o
第2处
, c2 D0 P. V& r+ L- J& ~% Q
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    : N) J6 H+ j+ Y% [" Q0 o7 z) {* i+ `
  2. {& Q7 F7 J) S" i/ {
  3.   int v4; // eax
    . W& P8 F( C3 w& J
  4.   GLsizei v5; // eax
    , K; r0 k) g- ]& ~2 Z% N- G1 {* A3 v+ M# Q
  5.   char lists; // [esp+4h] [ebp-800h]: n6 ]: _/ k- {- {8 F; Q0 I
  6.   va_list va; // [esp+81Ch] [ebp+18h]
    " [1 \3 ?. c8 B+ ?5 A: ^7 \
  7. ) q, g2 r4 F. N6 f7 l
  8.   va_start(va, a4);$ l& U- A% r) Z9 c/ a0 b
  9.   if ( a4 )
    * w1 _8 x/ h6 c' w& Z* q- Y
  10.   {9 Y# r* d" t0 q( L$ O
  11.     sub_44F8A0(a3);
    ! j) J" v: J6 q8 j
  12.     v4 = sub_40BB44();
    % E) T( v5 j7 v( c1 @+ w
  13.     glRasterPos2i(x, v4 - a2);
    4 c( w/ p* H8 }
  14.     vsprintf(&lists, a4, va);
    5 O! M+ \0 q9 W* d
  15.     glPushAttrib(0x20000u);9 C: L) ?0 m: ]) P( C: y/ j7 T
  16.     glListBase(base);: F. }( y. P0 `$ B8 `) g
  17.     v5 = strlen(&lists);) I% Z( Z: d* ~" j& ?3 z
  18.     glCallLists(v5, 0x1401u, &lists);
    ) U; Z; ]5 v; S0 s8 O& t2 E
  19.     glPopAttrib();: U8 C. |" i( P" H, s" N
  20.   }2 Z/ |/ S; o* |
  21. }
复制代码

" }7 l# O1 r8 U2 \  N3 N: q: Y( p& A+ ~  p

/ k4 b- W3 g" ^1 ?; t( Y! f) n第3处
5 m/ j: O% Z- D! T/ e" y8 a

  1. 4 @' I# q, t' g6 ?5 d# L' h
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)  @5 y0 [5 w: n3 ~  j
  3. {, g' Y) Z7 Q  Q3 ~
  4.   GLvoid *v7; // ST08_4
    $ [2 ]; x- m0 ?/ ?; G- _: k
  5.   GLsizei v8; // eax
    6 }2 A- `& G) T
  6.   int v9; // [esp+0h] [ebp-1018h]5 i- `  q8 G/ |4 L) M  X
  7.   char v10; // [esp+8h] [ebp-1010h]
    3 i( K2 `% J/ Z% y- }
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    ( H; q+ k, C2 h1 i+ W; X7 F4 M
  9.   char v12[5]; // [esp+1013h] [ebp-5h]/ [8 ~7 U( }: I+ S$ O
  10.   va_list va; // [esp+103Ch] [ebp+24h]* c7 v' s& t* w+ F* p* s

  11. 4 Q4 y" Q* B2 w. p6 P& ^- M8 ]2 N2 Y
  12.   va_start(va, a7);
    6 r* \; h5 R" t6 m
  13.   v9 = 1;3 y3 N8 j8 v, `* p
  14.   if ( a7 )3 D) l  k% A  e: s4 r
  15.   {$ Y3 \. p8 {% @4 W- a7 |
  16.     vsprintf(&v10, a7, va);
    + ?8 L  m. N. a1 C0 }
  17.     glPushAttrib(0x20000u);. E: ]/ w# M! a# \
  18.     glListBase(base);
    * t! S" ]& u) `* Y* w! U
  19.     lists = &v10;
    ( e4 D! V* Z% o8 i% |
  20.     do
    4 R/ ~1 q& y( k2 @7 |
  21.     {/ o$ v. u$ g$ }
  22.       *(_DWORD *)&v12[1] = lists;/ j2 `$ h& T- B
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )" z2 M2 c! ~0 h  g9 _- {3 R" c  B
  24.         ++*(_DWORD *)&v12[1];
    ) u: w3 S9 z6 \2 |
  25.       v12[0] = **(_BYTE **)&v12[1];8 H' ]2 ]8 K- }" m/ ]3 A
  26.       **(_BYTE **)&v12[1] = 0;) W8 M7 W% T: w
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    9 q7 B& O: j1 j$ M; m/ W
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;
    ( e$ t" s7 Y& `# g
  29.       y -= a5;. U3 e0 ]- W' n
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);" b4 \/ b" `" \9 U# c- W
  31.       v7 = lists;
    + ]" I: K! v7 f. C
  32.       v8 = strlen((const char *)lists);5 }$ S7 ]0 _$ q
  33.       glCallLists(v8, 0x1401u, v7);  h& g1 M9 |% j' B
  34.       if ( v9 < a3 )5 A9 x2 l$ A& l* y& H# J" ?( S
  35.         a4 += 4;
    9 |4 W  D  `' Q+ ~& C
  36.       ++v9;5 t7 I# \- l4 c$ G
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);% {) m0 U% d( k( _0 B5 t( ?
  38.     }
    9 @: _, q& S/ p1 A9 N4 S8 v1 l' [3 u
  39.     while ( v12[0] );
      D0 t. Q# X" D$ t4 b" f
  40.     glPopAttrib();, v; q; Y8 U1 I' C# p7 `, a
  41.   }
    2 ~& ^3 |# D' _. {, V9 K, E. S) e
  42. }
    # h' n2 r% t" D- \( {
复制代码
' m) s( N# r% G: @1 l( c
调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
4 u* p) D( p6 I% x: r* A3 M: m! [: E. O& ~) F- B8 H9 {& V
  1. .text:004512B1 52                                         push    edx             ; char *0 c7 ~  ~( U- ]7 J( o% Z) `& z
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]
    + n6 `. z8 Z1 v# w
  3. .text:004512B5 50                                         push    eax             ; base
    5 @+ S) S) _5 ~& x; a& f( G$ J+ g# q
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    , ]( Z* A5 H# W; D
  5. .text:004512B9 51                                         push    ecx             ; int
    ' l" ?% A. C0 K" P) K+ v  l. O  J
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]: o8 [& g* D, o
  7. .text:004512BD 52                                         push    edx             ; int6 R$ R9 s  r% `7 C' N( S
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    6 |3 f8 v/ A5 u/ m/ U. B/ d
  9. .text:004512C1 50                                         push    eax             ; int
    ; w, N7 x: G2 W3 c2 A
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]
    # h* T  u& o# v7 w7 \; a3 Y
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]0 S0 @! s2 h) r
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    $ `+ T6 r) Q9 F$ L  O! a8 U5 g. R
  13. .text:004512CB 51                                         push    ecx             ; y+ T/ ]9 M3 v3 @. d, m- d
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    - v: |% S/ `3 C5 s: ~% Y" b
  15. .text:004512CF 52                                         push    edx             ; int
    ! K7 e1 e# c' ^. r4 q- R
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码
3 e, V" q# u& `  y; Z
chatGPT整理过之后,如下
: W/ E0 C* n7 f4 K* `$ Z- W1 q6 h9 t6 @8 H" r4 t
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    * J. S" u' n, q. p
  2. {
    5 d, t% _) ^6 L1 w$ F7 P
  3.   GLvoid *textData;         // 存储字符数据的指针8 O+ v2 D; q# {
  4.   GLsizei textLength;       // 字符数据的长度/ @& L; L, o8 P6 [
  5.   int lineIndex;            // 行索引
    1 @3 D: B1 v( ?$ r: S) u
  6.   char formattedText[5];    // 存储格式化后的字符数据) t: ?9 Q$ S0 }! p
  7.   GLvoid *currentLine;      // 当前行的字符数据指针5 C0 O* }2 |* v1 D& S0 H3 r
  8.   char buffer[5];           // 字符数据缓冲区
    1 `  V7 P/ E. a
  9.   va_list args;             // 变长参数列表
    * G0 l1 \' R  ~* ~5 w  Z( A1 w; w7 ^
  10. , f' A0 R) n# m* J% \1 \( G4 e( e
  11.   va_start(args, text);     // 初始化变长参数列表
    # b2 [6 {' Z* o" E! U0 R4 R
  12.   lineIndex = 1;            // 初始化行索引为1% N2 i8 D7 S" |) E- u2 E) L- c8 x

  13. + q" U. o4 |, W* |2 v  J
  14.   if (text)                 // 如果文本不为空! R7 q, W4 b0 q6 [  W
  15.   {
    + R0 v: R/ ~5 E
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中2 V& o; O4 q8 K: ~- t( P+ I. P
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态9 @6 ]0 W( [! m- U) D# n7 f  m
  18.     glListBase(displayListBase);          // 设置显示列表的基础值, S0 K; ?$ F3 O* Z
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置5 `! i1 g: f. p. ?* X; y
  20. - Q7 \2 A4 [9 N! U$ G6 m& D
  21.     do
    ) A; [) t: @0 J# A4 s$ Q  C* h
  22.     {7 w7 F2 \7 ]" g; Y
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素  E* v9 V) R( \% C+ v
  24. ) U+ b: v4 I% d/ E/ k0 t% R
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
    5 Z, N1 }9 E) m  p( k
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素3 q. S" S( i+ N: f: u2 @
  27. . ~) j+ _4 Q% e1 I. m2 m. C9 F  e
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    - g; \  L! Q8 i( x' n* \* {8 a
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符6 I6 k4 _7 g0 L. A: K( q
  30. 9 V/ ]  N! E. p6 k+ `
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)' t7 K; q" T7 N5 u" U' H2 v
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符# j6 X3 K5 B* ?1 `1 o: z0 V
  33. ( [/ ~+ B) i# d7 L+ K9 ]0 Z$ d
  34.       yOffset -= lineHeight;                // 更新y坐标& B% V8 I  ]" I/ V
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置) ^3 `# {% m9 _+ C' X0 D/ ?
  36.       textData = currentLine;              // 将textData指向currentLine; W7 x9 m4 V" \( f% r2 s. m) U
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度
    ; L, {9 F" K1 v) M; r. v
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表, w$ ]3 I9 J& J  D
  39. * q5 n- }) d# M/ H7 G
  40.       if (lineIndex < numLines)) T- Z1 j  j# D2 p1 `9 e: n
  41.         lineOffset += 4;                   // 更新lineOffset: g" S& n$ j; a8 h
  42.       ++lineIndex;                         // 递增行索引
    8 J) {/ g! Z: y
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    9 {: T) }0 j+ o) }! I
  44.     }5 _) H5 L/ L9 [+ R  O5 p. o4 |
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环; L* u. K9 b6 b$ s' V3 r
  46.     glPopAttrib();                          // 恢复OpenGL属性状态
    4 I* m. o, X' Y. h8 t2 b
  47.   }
    . D6 W# |( i/ X" X6 W% t
  48. }
    9 L. @; S0 e( u
复制代码

  ~9 j  N# J- U% P, i! j含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前, G5 d2 a7 y) I9 t% M% F

- t" O. {2 B# Aint xOffset,      字幕的x坐标. n# c7 Y9 `' l, @
GLint yOffset,    字幕的y坐标9 j4 w6 N( [! Q/ w% q2 L
int numLines,     字幕的行数(较长的字幕为2,一般为1)
# ^' Y1 |* s$ z& B. Cint lineOffset,   这个需要再研究
% C; _- ~, H: cint lineHeight,   字体高度(或行高)
2 }) p# n. f0 z: ^GLuint displayListBase, 这个字体对应的base值9 }6 N( j# t* @5 _
char *text, ...         字符串" B* G1 u+ m7 @. p3 @

8 H# p% |8 I3 k6 C) B
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来+ x( h9 j6 R* r5 J
回复 支持 反对

使用道具 举报

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

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