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

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

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

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

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

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

本帖最后由 shane007 于 2023-9-5 16:49 编辑 - h' e1 K& x, A7 a" j# K
) Q5 G9 f) @& x
这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎
# ]' o# j0 R4 q2 o) N因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。! \9 a: H8 ?+ e
https://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
  l0 b# ]2 X% A9 h# Q% Z第1处1 e+ Q. C. u& i
  1. void sub_451474(char *a1, ...)
    2 L2 M: c" h4 x# P% _  k
  2. {
    + {/ J  X  i8 O1 X1 u8 ~
  3.   GLsizei v1; // eax
    . f$ R+ l5 p7 q! \2 d. D
  4.   char lists; // [esp+4h] [ebp-800h]$ f2 u9 L2 M$ c- ?
  5.   va_list va; // [esp+810h] [ebp+Ch]' x1 Q  b# o5 z! F

  6. # G& ~. e# E3 Q: B+ X
  7.   va_start(va, a1);
    7 w% U/ n. f) e5 ?7 U3 e, c: i7 N( s- T
  8.   if ( a1 )
    ! [: }# G# a( r, v
  9.   {
    3 g* b1 t2 s! F  {
  10.     vsprintf(&lists, a1, va);
    ) r. w: w( B& z+ |
  11.     glPushAttrib(0x20000u);  `5 F% u  N# y( B5 ?' P" A
  12.     glListBase(base);6 P9 p$ a; G8 B& g: X' j0 ]/ P
  13.     v1 = strlen(&lists);; z# u# U, O0 F8 S
  14.     glCallLists(v1, 0x1401u, &lists);* h( Q" Q7 R2 Q5 g
  15.     glPopAttrib();$ y8 F5 {0 N# n1 G
  16.   }
    & b6 S. J/ q4 u% r  U  K
  17. }
复制代码
' I$ |- m1 r+ i# W; e  U& a

% {/ ?# ~, s( }, k0 w3 b) L, L0 Y* `5 P3 C, a
第2处
" V2 |. ?" Z" m5 I7 m2 y8 N
  1. void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
    % Z6 _6 {$ ^( p  e, k7 K
  2. {8 ?, A% y# E+ k  }! ]& ?
  3.   int v4; // eax
    1 D  J6 f( H6 V: a
  4.   GLsizei v5; // eax& w, a! L2 x/ T2 u
  5.   char lists; // [esp+4h] [ebp-800h]- p9 V0 I6 T+ N
  6.   va_list va; // [esp+81Ch] [ebp+18h]4 E) t5 b7 R# N1 V2 J' U' p/ c& n5 j
  7. 9 S& x7 d# \! b
  8.   va_start(va, a4);; J% _3 `( j; K( w0 z$ q
  9.   if ( a4 )/ ]& W' F! \# t# Z/ x3 m
  10.   {# \! ]2 s0 V, D1 |0 l  i
  11.     sub_44F8A0(a3);
    / D- Z, {& U6 }: [! p8 E# Q2 E
  12.     v4 = sub_40BB44();! m: \- J( A2 q# @
  13.     glRasterPos2i(x, v4 - a2);
    ! S; E5 C% N, h' {
  14.     vsprintf(&lists, a4, va);
    3 V1 g* a* k6 s
  15.     glPushAttrib(0x20000u);$ v1 H: P, u9 ^
  16.     glListBase(base);
    1 r; d/ G: S! V, Y+ E  a& W- }' U
  17.     v5 = strlen(&lists);/ h. l6 N+ H7 m- Z
  18.     glCallLists(v5, 0x1401u, &lists);; A! W4 O$ \3 z9 e2 ]! f: R
  19.     glPopAttrib();
    : ~& _3 X: S4 ]4 C" l7 j2 ]
  20.   }( `1 \, f% U3 ]1 z. b
  21. }
复制代码
) b9 Q$ ?$ [" Q  a
8 y/ _! `! Q3 R8 C

5 A2 _/ g( m% p# C第3处
/ N+ M! C& [9 p: f' g% T

  1. * ~- x' }5 `, j' j' ~! [/ z
  2. void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
    1 s8 e5 P. h" T
  3. {
    $ B/ Q3 E% X8 J4 Q; u, E/ E7 d
  4.   GLvoid *v7; // ST08_4" o% G# W* b( ^9 u9 B
  5.   GLsizei v8; // eax; s( U! Y/ d% b0 {
  6.   int v9; // [esp+0h] [ebp-1018h]
    $ Y, q7 v5 c  C9 j* [. `2 l
  7.   char v10; // [esp+8h] [ebp-1010h]
    0 o2 u" [. c+ o
  8.   GLvoid *lists; // [esp+100Ch] [ebp-Ch]
    , F8 {) R3 |4 w0 Y5 t% I& G/ E4 P
  9.   char v12[5]; // [esp+1013h] [ebp-5h]
    % T: F( j  }1 _; E3 o
  10.   va_list va; // [esp+103Ch] [ebp+24h]6 Y+ {% u  y" N/ e# r

  11. ( I# p; S. c, e! S& I
  12.   va_start(va, a7);
      ~# ]: o4 \5 y2 Y/ y5 p
  13.   v9 = 1;
    - A& `; n" {; w
  14.   if ( a7 )
    , n/ a* C4 u0 u- a
  15.   {$ n/ O# Z0 D: n$ {
  16.     vsprintf(&v10, a7, va);
    5 L3 c- ?) ?' y' Q- k. H
  17.     glPushAttrib(0x20000u);
    ) w8 @1 \% s! X3 y" q5 g( t" {9 n+ i- |
  18.     glListBase(base);; |* t$ E2 h' T/ m4 O
  19.     lists = &v10;
    : k; [0 }$ e  o* N& r
  20.     do
    8 e, `" h' \4 }1 W6 k7 @# i0 N6 H
  21.     {8 f7 s, R8 C4 f- x& H1 Z% K
  22.       *(_DWORD *)&v12[1] = lists;0 Y7 |6 ], e- B- \8 X
  23.       while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )
    % _) Y# H; h5 \2 ]
  24.         ++*(_DWORD *)&v12[1];
    ; F/ K+ |+ U* o. m$ h8 G
  25.       v12[0] = **(_BYTE **)&v12[1];$ a9 V# e  h" k7 G' ^' ]; g; q
  26.       **(_BYTE **)&v12[1] = 0;, I, y2 m0 J$ ~5 S
  27.       if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )
    1 m& S* q5 r3 C
  28.         *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;+ N- X. T1 D. [6 z! V! s! }- V4 t/ z
  29.       y -= a5;& S8 f4 |& z( n+ O
  30.       glRasterPos2i(*(_DWORD *)a4 + a1, y);
    $ c' {+ P5 B' B0 E# o4 ]/ g- [3 }
  31.       v7 = lists;
    * Z8 t7 I8 Y& n
  32.       v8 = strlen((const char *)lists);- n) y1 y7 [: ~+ v# I
  33.       glCallLists(v8, 0x1401u, v7);
    $ Y: E" r* c" y" ^# r
  34.       if ( v9 < a3 )3 O6 u( h9 T- G% Z- e$ Q
  35.         a4 += 4;4 b  A1 Q' o8 R9 L& j8 _+ V
  36.       ++v9;
      g9 x. j1 j: K5 G" k
  37.       lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
    & F% k! ]0 j' N7 ?$ p3 \3 R
  38.     }
    0 u5 |, A8 }1 _
  39.     while ( v12[0] );
    ) k- J) E$ V6 w- P, [% q) k/ c
  40.     glPopAttrib();
    ! x2 A) t3 y2 J+ h
  41.   }
    & x0 y2 f# S3 i
  42. }: @% \7 B) ^8 Q& u' k. h
复制代码

+ i$ o/ V4 J* J# A# a; T+ L0 P2 ?. w3 B调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_4518105 Z3 {4 a" ^8 P( B0 j* V5 D

1 S6 n' ?7 `' S' W
  1. .text:004512B1 52                                         push    edx             ; char ** v, y! n) e: N# W" N' h# b
  2. .text:004512B2 8B 45 30                                   mov     eax, [ebp+base]5 k& Z; _1 f* G. P( U
  3. .text:004512B5 50                                         push    eax             ; base
    ' A  s- D9 ]7 \+ F
  4. .text:004512B6 8B 4D 20                                   mov     ecx, [ebp+arg_18]
    4 _1 u% Z+ {  J+ W+ [
  5. .text:004512B9 51                                         push    ecx             ; int. E1 ]1 C; h" S$ W% W
  6. .text:004512BA 8B 55 1C                                   mov     edx, [ebp+arg_14]
    # _/ G* d& r& W
  7. .text:004512BD 52                                         push    edx             ; int
    # b' a; u  J5 G
  8. .text:004512BE 8B 45 18                                   mov     eax, [ebp+arg_10]
    2 D& @% x7 U, m
  9. .text:004512C1 50                                         push    eax             ; int/ l+ g; ~/ p/ O! p# ]/ S
  10. .text:004512C2 8B 4D 0C                                   mov     ecx, [ebp+y]# C0 C  u1 c! y* Q! y" F0 F4 U
  11. .text:004512C5 03 4D 14                                   add     ecx, [ebp+arg_C]
    - q$ y/ A9 o1 `* j9 g- _6 O; B1 ~
  12. .text:004512C8 03 4D 24                                   add     ecx, [ebp+arg_1C]
    ( ]8 T/ R4 J2 q
  13. .text:004512CB 51                                         push    ecx             ; y
    2 V0 s5 t$ m- S
  14. .text:004512CC 8B 55 08                                   mov     edx, [ebp+x]
    ! ]% {. ?5 `! V0 T* Z
  15. .text:004512CF 52                                         push    edx             ; int
    . E5 y/ f& |/ j5 k
  16. .text:004512D0 E8 3B 05 00 00                             call    sub_451810
复制代码

# j- v2 v& @) n' P. Q& {chatGPT整理过之后,如下. g" T: i2 m; i' H
' y* u, e, m; n
  1. void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
    / V4 z5 Y! w$ P% f/ ~( p
  2. {
    ) V( A& ?' [7 C0 o) {' d7 ]
  3.   GLvoid *textData;         // 存储字符数据的指针
    ; j, m- ?# E, ~
  4.   GLsizei textLength;       // 字符数据的长度
    6 ]8 I& q2 k8 v$ S- @
  5.   int lineIndex;            // 行索引
    - v& T2 q8 Z: a8 n6 N
  6.   char formattedText[5];    // 存储格式化后的字符数据+ v% G; ?* [) A
  7.   GLvoid *currentLine;      // 当前行的字符数据指针1 F# R1 `6 [  Q9 l, r
  8.   char buffer[5];           // 字符数据缓冲区- D9 F6 |# l, G) Y# c5 l. k6 n4 S/ a
  9.   va_list args;             // 变长参数列表9 A# y/ }& w  S$ B' \$ k; V# W- }" O
  10. 3 B' `  H/ c5 e3 z, Q: p3 R
  11.   va_start(args, text);     // 初始化变长参数列表9 \; l. k6 F) ~% c, n" o& D
  12.   lineIndex = 1;            // 初始化行索引为1  }4 o8 y! j& j, o
  13.   p: a. o: K/ m6 s# M$ ?; v( @( t7 R
  14.   if (text)                 // 如果文本不为空: X1 U, Y2 p% ^- y
  15.   {2 B0 N+ K$ B# p  T( Q
  16.     vsprintf(formattedText, text, args);   // 使用变长参数列表格式化字符串,并将结果存储到formattedText中) _+ ~8 i2 g4 x) J% q7 ~" I* m
  17.     glPushAttrib(0x20000u);               // 推送OpenGL属性状态
    " l+ J. H; M. V& V% @5 n- n8 {" A
  18.     glListBase(displayListBase);          // 设置显示列表的基础值5 w6 g4 Y: ?% N2 I9 l* c. V4 F
  19.     currentLine = formattedText;          // 将currentLine指向formattedText的内存位置
    5 p+ X+ o  z8 {

  20. # l. p* T: k% C7 Z
  21.     do, q. Z+ w0 J! t
  22.     {  o' U! e" r8 E; {  x+ \
  23.       *(_DWORD *)&buffer[1] = currentLine;   // 将currentLine的内存地址存储到buffer数组的第二个元素: U; Y6 g7 K% L: w+ a% z" r- S: |
  24. 0 ~7 i# d7 I- @# {( d+ p
  25.       while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10)   // 循环直到遇到换行符或字符串结束
    : Z( ?# X" m! x/ H- r# `
  26.         ++*(_DWORD *)&buffer[1];   // 递增buffer数组的第二个元素
    $ _! U& [, o( M$ W$ `
  27. 5 d" Z5 T8 p" b& _
  28.       buffer[0] = **(_BYTE **)&buffer[1];   // 将换行符存储到buffer数组的第一个元素
    7 I# z8 p4 j8 C; G0 s2 a3 L. B9 F
  29.       **(_BYTE **)&buffer[1] = 0;           // 将换行符替换为字符串结束符
    % N) a  F6 d! s* U* J* P5 _
  30. , ^3 r5 _; G) l+ l9 X
  31.       if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
    . U) E& |& D. @6 f+ M
  32.         *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0;   // 处理换行符和回车符
    ; P. j: a7 h( t' P8 u

  33. * y6 I, M6 d. L
  34.       yOffset -= lineHeight;                // 更新y坐标! `1 r" S* d, \0 R# K, b$ m
  35.       glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset);   // 设置光栅化位置4 n" k7 ^, h; {# g$ q/ R  `
  36.       textData = currentLine;              // 将textData指向currentLine
    ( _' ]3 o! _: }7 W2 k- _$ W7 ^
  37.       textLength = strlen((const char *)textData);   // 计算字符数据的长度% }7 g+ ]- @( l, I: A
  38.       glCallLists(textLength, 0x1401u, textData);    // 调用显示列表
    ! L; v5 [  ~! l( g8 O1 G- [- J8 ]& @9 r) _

  39. * U" U) T% `7 \5 |; u
  40.       if (lineIndex < numLines)) Y; n+ m+ v. Q! H2 V9 [: ^
  41.         lineOffset += 4;                   // 更新lineOffset
    # \$ P/ r) Z  p
  42.       ++lineIndex;                         // 递增行索引/ @! K! H, X; Z" M: a. f" {  a
  43.       currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1);   // 更新currentLine指向下一个字符数据
    4 a' e2 h- @. y- d2 @8 b) E
  44.     }0 J$ h5 T: P: z
  45.     while (buffer[0]);                     // 当字符数组buffer的第一个元素不为0时继续循环
    , L% L8 C; D' g: b, Q( h6 T* H
  46.     glPopAttrib();                          // 恢复OpenGL属性状态2 H) o; e* g& M4 J3 }- Y7 H) z
  47.   }+ P# U7 V8 V/ A, m/ F
  48. }
    ; b2 y+ `7 O* b* Z" J: x
复制代码

* _; [0 _. h8 p" e9 V含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
: p1 R6 V4 K+ G1 ^
% j/ w0 G, e) N. ~* @6 v) p# Bint xOffset,      字幕的x坐标
8 d1 a) j+ L# y, cGLint yOffset,    字幕的y坐标
1 X" g; H; q6 W. Tint numLines,     字幕的行数(较长的字幕为2,一般为1)& r& V$ u# M. U
int lineOffset,   这个需要再研究4 M' D4 k8 N6 C+ ]+ \+ t
int lineHeight,   字体高度(或行高)
& |1 n6 Y' V& B& R, U( u! J% n8 tGLuint displayListBase, 这个字体对应的base值  N4 R: k/ S) [+ M# T
char *text, ...         字符串
3 D  v! \* x" d* g, N( T* D
+ Y  m  c5 p& H& A5 I9 V5 _
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 很美好很美好 很差劲很差劲
回复

使用道具 举报

沙发
 楼主| 发表于 2023-9-4 18:53 | 只看该作者
顶上来,顶上来
- I0 v; V$ o* @" U1 ]4 h
回复 支持 反对

使用道具 举报

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

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