本帖最后由 shane007 于 2023-9-5 16:49 编辑
# n: \7 l. \# D+ ]: \3 T: [+ z
( B0 |( _" H& C- {4 K" L这个游戏也是opengl的游戏,本游戏的和魔法英雄历险记(Tale of a Hero)这个游戏用的是同一个引擎2 Q6 j2 w$ t. |/ v) R* ]7 u9 P
因此代码基本类似,对glGenLists的调用处也是6处,因此参照以上帖子即可。
1 S. F+ d9 u$ G* p1 P qhttps://www.chinaavg.com/forum.php?mod=viewthread&tid=154081
1 e' |% C' K! S& d1 }8 u7 K第1处
+ Z0 Z" ]( d7 l9 ]7 |- void sub_451474(char *a1, ...)0 d9 @1 q) d, v1 s7 c
- {6 l: e1 |- @5 z/ S3 h( K
- GLsizei v1; // eax
0 L1 ]% x0 q* g: g( T9 h# h - char lists; // [esp+4h] [ebp-800h]
8 V- Q9 _& L; D7 g" x - va_list va; // [esp+810h] [ebp+Ch]
7 t4 [( @# ^* g9 X
& l8 n G+ w/ \) S4 I; D7 ]- va_start(va, a1);' |) x0 _" l3 z6 y) j9 z w
- if ( a1 )
1 A' C' S, T9 b# i% j4 ] - {' V8 P# ^9 S i @7 \* w
- vsprintf(&lists, a1, va);
- { b: _8 A l - glPushAttrib(0x20000u);
3 L. w6 a' h7 r7 L& r - glListBase(base);3 p3 q. i2 z2 G7 b
- v1 = strlen(&lists);
: r' f4 K( U0 E0 I - glCallLists(v1, 0x1401u, &lists);% e' d; N8 k! | [+ o4 ?
- glPopAttrib();
5 r' U5 @; R) B+ t7 @ - }0 [* u/ g: D% A3 g4 W5 ^; m( l: o% b
- }
复制代码
5 B% Y. B0 H( F0 b$ V- g
$ t5 \% P- ~; z- t
% l1 G _5 Q; K7 w+ x第2处 e6 z, Z Y* z1 @ n; e
- void sub_4514F6(GLint x, int a2, int a3, char *a4, ...)
* M$ p+ u8 ?2 q8 ]0 i- g7 a - {6 ?% |9 X( F5 N$ e4 ?' p- k
- int v4; // eax* T" w! b, ]# a$ T* `) @
- GLsizei v5; // eax
2 D8 X% V) u! i* b - char lists; // [esp+4h] [ebp-800h]
9 E+ o1 L) r; @( W; y- x - va_list va; // [esp+81Ch] [ebp+18h]! Z* _% h/ y' D, ?
- 1 u/ D% q$ Y) Q5 ~7 l" ]
- va_start(va, a4);
4 P5 Q+ c/ r1 Z - if ( a4 )2 D' e: |9 b, }/ W; e4 b- [0 `
- {
; x6 m6 R" C/ _9 ~6 u - sub_44F8A0(a3);
0 f' N- q+ Z* ~ - v4 = sub_40BB44();
) _& w9 }* P; R2 h+ m: `2 ^ - glRasterPos2i(x, v4 - a2);+ D) r# g" D! x( |$ C
- vsprintf(&lists, a4, va);& ]7 ?+ f. M6 |' a9 N
- glPushAttrib(0x20000u);
7 m) s" ]7 w# S: I2 t H& r - glListBase(base);
+ a! D, }3 n3 o5 B, J - v5 = strlen(&lists);% W, s. \0 J3 }" ~) q4 c
- glCallLists(v5, 0x1401u, &lists);7 {% S3 |9 D9 r9 j
- glPopAttrib();9 Q% ~2 M# e, D' T
- }/ W) B( d! s' H3 G7 w: z ~
- }
复制代码 4 L' x7 K6 A$ t1 @5 H7 J3 A7 a
! S e' d0 o3 N8 L+ `6 S$ n* b* v$ ^7 y1 D7 n2 N9 F( N) ]) F1 I
第3处" M7 J) _9 W' @+ M# Y; ~: m5 y
- ! D2 ~/ @7 @% k1 [
- void sub_451810(int a1, GLint y, int a3, int a4, int a5, GLuint base, char *a7, ...)
( F [+ {( G& K! C& \1 I - {3 X; q) x, X1 z1 ?5 f, |
- GLvoid *v7; // ST08_4
1 L& T0 {5 U7 k# [) b4 a- y. i - GLsizei v8; // eax
7 y O$ ]8 Z, U! Q - int v9; // [esp+0h] [ebp-1018h]
, V2 S* d; M$ z - char v10; // [esp+8h] [ebp-1010h]+ C2 |0 a6 n" B2 s
- GLvoid *lists; // [esp+100Ch] [ebp-Ch]; L9 [7 B \. B2 `! x5 u( a' ]3 u4 f7 S
- char v12[5]; // [esp+1013h] [ebp-5h]; q4 p0 b H6 h1 U0 q( G+ ?
- va_list va; // [esp+103Ch] [ebp+24h]% W3 K$ g0 t: C' @* [
2 v* P# y# \. {4 H b" ?+ J- va_start(va, a7);+ {% ]6 {( G6 ?4 `: y
- v9 = 1;1 @$ A3 S8 z: T# B2 V
- if ( a7 )
! ^% d \3 X/ Q - {# x2 t( y# v! [% }3 [0 P6 K' r
- vsprintf(&v10, a7, va);
9 `3 I( X2 \7 Y5 f0 D. ]! V - glPushAttrib(0x20000u);5 ~: Z2 i0 S5 M# B% T5 p- q, c/ X
- glListBase(base);) ?- j% }/ ?* q7 R/ u5 |5 h
- lists = &v10;6 q7 \: x9 O4 s; M
- do
7 _1 h5 B# m; ^5 u8 T - {% r+ C9 A! f* x4 q( J
- *(_DWORD *)&v12[1] = lists;
# u/ }' O4 T: \. [9 X! I - while ( **(_BYTE **)&v12[1] && **(_BYTE **)&v12[1] != 10 )" C, X( e2 Z2 o* k! V
- ++*(_DWORD *)&v12[1];
6 ?* r s/ D5 z. t: Z - v12[0] = **(_BYTE **)&v12[1];
! \; [$ o) P% w0 A0 O3 K - **(_BYTE **)&v12[1] = 0;- a7 Y0 f+ {3 E% X4 K% @
- if ( v12[0] == 10 && *(GLvoid **)&v12[1] != lists && *(_BYTE *)(*(_DWORD *)&v12[1] - 1) == 13 )! h7 ~0 G2 x" x+ u8 `
- *(_BYTE *)(*(_DWORD *)&v12[1] - 1) = 0;* [% _# h- y% x$ r a
- y -= a5;
) h5 W+ r, K0 e& u - glRasterPos2i(*(_DWORD *)a4 + a1, y);+ R( g3 b- `+ ?' Z$ s# E5 }& }; r
- v7 = lists;
4 A- _( g, ~! m3 b" H, P - v8 = strlen((const char *)lists);
. g) x# f: ^* l% g1 O - glCallLists(v8, 0x1401u, v7);! a, ]; V0 e1 v3 ]* c: V/ L0 p) i
- if ( v9 < a3 )! L; s* f: {) o U" ]: G8 z
- a4 += 4;
# e Z7 r* e1 ~: |5 h; F - ++v9;/ A7 Z0 b, V: q# A O# |
- lists = (GLvoid *)(*(_DWORD *)&v12[1] + 1);
+ r; e7 E" \) Q$ }5 ?) U8 u+ v - }
3 k) w( F2 A- a0 a8 Q b0 \, t - while ( v12[0] );
6 Y# a3 p i4 r( {( R. Y+ s - glPopAttrib();) [6 p+ B! d2 c. W5 G1 Y1 L7 H9 @
- }5 p+ D: i5 y7 i( [4 H% g
- }/ w) |8 a$ H& m
复制代码
7 ?1 u, m Y' C) ~) h调用处,将 这句nop掉之后,游戏对话字幕不显示,因此,451810是对话显示函数。.text:004512D0 E8 3B 05 00 00 call sub_451810
. ]4 C7 H: s9 c( E2 \) g. s. L8 C6 A+ F! B& |9 Z5 f o' |
- .text:004512B1 52 push edx ; char *3 ?+ u1 Q2 y: o7 @+ ~
- .text:004512B2 8B 45 30 mov eax, [ebp+base]
7 t; |5 F c" e# g; U% M - .text:004512B5 50 push eax ; base0 f5 d4 b& C5 y1 N7 E/ l3 S2 ~& H
- .text:004512B6 8B 4D 20 mov ecx, [ebp+arg_18]4 m# L2 M3 ~) g0 U" R- U" m
- .text:004512B9 51 push ecx ; int
. x! Q. e, E/ z6 o4 S* z - .text:004512BA 8B 55 1C mov edx, [ebp+arg_14]
. N5 n* \" R# s! N$ q6 i6 N - .text:004512BD 52 push edx ; int7 L a7 G$ g4 J4 f7 ^. l( T
- .text:004512BE 8B 45 18 mov eax, [ebp+arg_10]
0 D9 [1 ^/ L G8 d1 v - .text:004512C1 50 push eax ; int8 u1 |) ]2 J* ^( k2 ?2 \9 D# W
- .text:004512C2 8B 4D 0C mov ecx, [ebp+y]( T6 q& a. G3 {1 i
- .text:004512C5 03 4D 14 add ecx, [ebp+arg_C]
D' c, ~) h# ^ - .text:004512C8 03 4D 24 add ecx, [ebp+arg_1C]
, g& x9 | c3 W" l5 V+ ~ - .text:004512CB 51 push ecx ; y" |; z! y6 J2 z0 |! Y
- .text:004512CC 8B 55 08 mov edx, [ebp+x]
8 x# A6 E# [; i) ~* |3 n B - .text:004512CF 52 push edx ; int* E( w2 {2 l! {/ P! i2 J; `5 G
- .text:004512D0 E8 3B 05 00 00 call sub_451810
复制代码
1 f3 s: o* r9 a3 c" mchatGPT整理过之后,如下% d* Z& `) j- T$ [! l
- W5 ] O7 p9 @
- void renderText(int xOffset, GLint yOffset, int numLines, int lineOffset, int lineHeight, GLuint displayListBase, char *text, ...)
1 ?: K6 G0 N2 B5 G3 `" S - {
, B# _0 ~9 w5 G7 u! G& I& u) G - GLvoid *textData; // 存储字符数据的指针
! J$ t7 d9 B% d( f( \ - GLsizei textLength; // 字符数据的长度# R2 u y) s9 F6 K
- int lineIndex; // 行索引
) a# u0 T4 F, A+ }2 ~ - char formattedText[5]; // 存储格式化后的字符数据
3 P+ S( n" o& `/ M B - GLvoid *currentLine; // 当前行的字符数据指针% @1 g5 D" i A( J
- char buffer[5]; // 字符数据缓冲区9 L2 }/ C/ w% Q) @) j. i' j1 L
- va_list args; // 变长参数列表
3 z& n5 E: A: P' I( i
$ L" }" p6 C$ X9 }& X- va_start(args, text); // 初始化变长参数列表8 G7 Y( K) y* Z: Q- N$ q3 Z( l
- lineIndex = 1; // 初始化行索引为1
% n0 z1 ~3 c! R4 Z" Y - : S9 d( L) `2 \. |5 }" |" A
- if (text) // 如果文本不为空1 g0 O" v$ [! t1 ]4 ^2 u
- {
: V( a7 E' S1 @# c( b1 g f- A. P - vsprintf(formattedText, text, args); // 使用变长参数列表格式化字符串,并将结果存储到formattedText中. z, P5 w% j2 g
- glPushAttrib(0x20000u); // 推送OpenGL属性状态
6 N( Z! V% ?6 i a - glListBase(displayListBase); // 设置显示列表的基础值
+ C+ Y' H/ k" u - currentLine = formattedText; // 将currentLine指向formattedText的内存位置 M6 A" O+ `3 b$ G1 @' s& D/ h
4 A0 L! _1 N1 o/ J- do
6 G' Z- p! B; x0 T& v3 B2 l5 \ - {* }7 S( _) @# ~- h p& C
- *(_DWORD *)&buffer[1] = currentLine; // 将currentLine的内存地址存储到buffer数组的第二个元素8 @" z( v% }* R( b5 @4 X A _
- , Z! Y+ p6 r( u- Y) }" [
- while (**(_BYTE **)&buffer[1] && **(_BYTE **)&buffer[1] != 10) // 循环直到遇到换行符或字符串结束
k x; T% \. O+ s8 Z* G* S - ++*(_DWORD *)&buffer[1]; // 递增buffer数组的第二个元素
2 r* K1 u& Z: X
+ m1 R( C/ x1 w5 G2 i$ f3 M2 M0 S- buffer[0] = **(_BYTE **)&buffer[1]; // 将换行符存储到buffer数组的第一个元素
( V7 M! l9 {: Q# p, x - **(_BYTE **)&buffer[1] = 0; // 将换行符替换为字符串结束符+ T# n& `; o0 V
- - V. B! ?. z& |9 v
- if (buffer[0] == 10 && *(GLvoid **)&buffer[1] != currentLine && *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) == 13)
; C+ l3 b2 r- T - *(_BYTE *)(*(_DWORD *)&buffer[1] - 1) = 0; // 处理换行符和回车符
{4 \4 M' F/ M6 S" a K
0 r$ c7 W: |2 V; r1 Z- yOffset -= lineHeight; // 更新y坐标
; x3 G" Z+ j, N: i9 j/ a& p - glRasterPos2i(*(_DWORD *)lineOffset + xOffset, yOffset); // 设置光栅化位置
/ M9 C9 D, B% V - textData = currentLine; // 将textData指向currentLine9 X, t% R$ @7 c( Q3 g5 a
- textLength = strlen((const char *)textData); // 计算字符数据的长度
8 z, [% c7 k& e9 _* g+ ]& }& c* ~ - glCallLists(textLength, 0x1401u, textData); // 调用显示列表9 E' }/ a6 ~3 W
* O' n- r3 P' y ~( O) A; R9 x- if (lineIndex < numLines)
+ G; G8 H) H# g4 M - lineOffset += 4; // 更新lineOffset
) }. r9 v0 c* }4 c T# ]; U* Q - ++lineIndex; // 递增行索引
. ~+ n& D" d0 H4 w# S; w - currentLine = (GLvoid *)(*(_DWORD *)&buffer[1] + 1); // 更新currentLine指向下一个字符数据
' \! A+ |6 {4 f - }
( z$ z- H" \( l5 _1 I; {" z9 S - while (buffer[0]); // 当字符数组buffer的第一个元素不为0时继续循环4 c% H! Y9 T, [. Q9 s
- glPopAttrib(); // 恢复OpenGL属性状态$ O8 v1 i2 l& f2 [: _; o& w5 c
- }( r: g2 v) f. ]0 O" d: P7 D7 t5 g
- }
- u* d8 E) v0 T" j: q! j
复制代码
" }% T) o8 L% q0 R含义解释如下,设置字符串颜色还需要寻找,也许是在调用此方法之前
6 C4 v: ?3 K- J: H% ]0 }7 t4 N& I) L# B# @
int xOffset, 字幕的x坐标
: [1 C! A! |2 U3 mGLint yOffset, 字幕的y坐标
8 B8 S9 R- i$ g2 r7 _$ wint numLines, 字幕的行数(较长的字幕为2,一般为1)
0 ~4 N6 M$ ?: lint lineOffset, 这个需要再研究4 n( i2 f$ A7 e3 N% e
int lineHeight, 字体高度(或行高)
6 G" `: C( z2 @4 C/ A0 oGLuint displayListBase, 这个字体对应的base值4 v, T- {/ P( O! z! j3 T& X- k
char *text, ... 字符串) C7 B& x( E' y/ w; b4 }5 S
7 h: y) V! ]6 w$ h2 O% q t h& ]
|