本帖最后由 shane007 于 2023-8-12 09:10 编辑
4 }& F# w- j0 ]! W _" r% x# M8 }9 E* S9 J/ h! d) G& i3 r. Y
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。! f* R$ u5 E4 i5 d: \5 `! M
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
" l: u& n9 J* A+ ^8 b2 f* R3 O2 Y6 w8 W
比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。0 `9 t8 r- B1 y1 W, [. Q
RUEAN.IND
7 f6 q6 n# b3 ^ ruean.Txt6 ^9 o' |8 @ k6 V& ~
$ ?; _" m$ s/ Q$ ^) u *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。1 e* N: }2 J9 \
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。% m- i m* Y( U3 K1 h
, w C0 [6 [* z' j) |$ Q+ } G7 K" `7 |/ z. J- Q
*.TXT的解密代码如下
" x8 D4 I+ i; d: U, h- int TalkManager::countBoxLines(int idx, const Common::String &file) {8 y4 l5 Q6 k; e" s4 Z# w# ]
- _vm->_fontMan->_fontFixedWidth = 11;7 h; @, Q) z2 ~) {' C
7 e& N4 O; D4 a5 P; o, K- // Build up the filename
9 `2 o/ q, `9 a; k - Common::String filename;4 T! @9 ^* s k# i. R& |2 f
- Common::String dest;4 W/ K1 ?$ y8 m7 ^
- filename = dest = file;
, @; Y' P/ j, D: T8 Q3 Y; Z& { - while (filename.lastChar() != '.')" c2 k1 l; T, }) x+ |3 _ J
- filename.deleteLastChar();& q' k$ U& |* p0 r( g, I2 s
- filename += "IND";
# v4 u8 Q j! ~1 |
6 j; P, ]4 u5 ~! u8 p7 Y F' |- Common::File f;
* r: s3 i3 C; W0 Z - if (!f.open(filename))
0 ]- `- Y9 i/ j G8 h. E. @5 z3 Z2 U, \ - error("Could not open file - %s", filename.c_str());! M: Q& W" X5 U* P0 D2 ] x" a0 a
- int filesize = f.size();
/ }6 K0 d# f4 q - assert(filesize < 16188);: N0 }# k8 o# Z) Y2 M6 m" o1 n# s+ F
) M+ e8 w- N' F8 W1 s0 \9 i- uint32 indexData[4047];0 \& k- K1 G; I
- for (int i = 0; i < (filesize / 4); ++i)9 U. a; s" V! l; ^6 x* C. @
- indexData[i] = f.readUint32LE(); Z9 Q$ J+ i7 k/ y* S
- f.close();9 u1 r% t2 i* K) J! d
' }1 U) o# d* _9 W) S9 A- if (!f.open(dest)), [. l; _1 u0 j7 J
- error("Error opening file - %s", dest.c_str());
" t# Z* k$ r) a - - y% d! s) Z4 e* g- C3 b# _2 D7 |
- f.seek(indexData[idx]);
% O& `! x. ^- p4 C - byte *decryptBuf = _vm->_globals->allocMemory(2058);
; Q0 y: I0 F* \6 m+ t - assert(decryptBuf);
8 C% W& g; ?: `, Y* M# Q - , t% ^1 ]0 Y* A! @/ @
- f.read(decryptBuf, 2048);! {+ e% A" X# _- k$ w! M' K
- f.close();4 @2 P d1 K% o
* f, z$ m3 p I: r; E- // Decrypt buffer) K- k% z, h% x( o
- byte *curDecryptPtr = decryptBuf;
- c. F6 `, V$ {3 ~6 N# { - for (int i = 0; i < 2048; i++) {) D! e% _- e4 h3 u. `/ A; t, @
- char curByte = *curDecryptPtr;* x" {0 y0 T& N. v
- if ((byte)(curByte + 46) > 27) {
1 w) X+ S. S5 y# W - if ((byte)(curByte + 80) > 27) {
, b3 p* x3 W6 N; _- U - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))0 l4 x) @7 T; h6 M( D6 i
- curByte = ' ';
; k+ _1 w% V- |: ~( k - } else {
9 j E; K4 U5 ?& j+ z - curByte -= 79;
9 y G3 I2 Z3 C( v. r - }) K" r4 }% L. Z/ ?# g5 A
- } else {9 H, C% B# g7 h; E
- curByte += 111;: @. x; ~* M2 A* A4 ^
- }$ o$ z1 h7 A& J/ f1 S: h
- *curDecryptPtr = curByte;8 z, K+ K- t$ J9 c6 g/ ^; c% C# h
- curDecryptPtr++;
3 V1 j4 Z' T3 E - }
% D1 m$ a# d% ]2 g2 c& x6 t
3 G( |) Z1 H4 G' {7 d ^- // Separate strings
+ j2 A& }" V( k H( \. o - for (int i = 0; i < 2048; i++) {
T, x: Y& {, N2 I! U) f - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
1 B( H" a, \+ A. J1 S% c: k - decryptBuf[i] = 0;
. z. M3 |1 I9 N1 M1 p1 h, t0 w8 E8 M' W - }
4 W5 x9 N; |3 W1 U# r; w* x& D6 m
( q v+ Z) I2 Y5 W) |* T- //add by shane0070 u, X) v7 U* |1 W+ Z g. X
- //debug((const char *)decryptBuf);$ C& s& O( ?+ r. A2 a
9 A8 c3 ~" L# \9 U1 K) [- // Check size of each strings in order to compute box width- d, `/ R' F& j& B4 j
- int curBufIndx = 0;
. q! {' \ w7 \* w& | - int lineCount = 0;
0 I: Y7 K9 u9 j6 O' } - int lineSize = 0;, p: l( `" r9 P4 N+ L9 W, Y
- char curChar;% `* v, I* v: ]" O. h' J$ P
- do {% h2 Q' U) J# }; ]! g. q6 |9 F
- int curLineSize = 0;2 N3 y" a' ~8 X0 H! Y
- for (;;) {9 P# m \* y/ M% d" v$ r/ ^
- lineSize = curLineSize;
: t# Q$ A! C( N - do {
/ X4 w# F0 O1 |# b( l/ y - curChar = decryptBuf[curBufIndx + curLineSize];
4 j. `0 D. n6 n# R3 o - ++curLineSize;, Q6 }2 v; S0 w2 z' W& V; o
- } while (curChar != ' ' && curChar != '%');4 O) {% O6 {" ]
- - A$ T2 ? P8 Z; ?' x1 i6 N
- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
! Z( |3 D- R( c9 i! B! o - if (curChar == '%')
: E5 L) g$ o2 X* A4 B' e - curChar = ' ';
. u- L6 y6 o1 m' C - break;# n$ ? J! a m0 D6 @# ^0 J u# |
- }
3 H* _, Z2 a( _ - & G0 s9 \+ E0 E) v- H( z& u: z
- if (curChar == '%') {# B2 H4 ?8 r1 m8 X0 \$ e, N
- lineSize = curLineSize;
f2 L F* E% ^3 g7 \ - break;
- ]; D& b0 Q# z! |' R0 W# w9 {' } - }+ A% e! M. G: U( I3 L% L+ g6 o
- }
9 ^4 B% i& k& Q1 K( A - ++lineCount;
' M0 F k6 \0 B5 Q& R - curBufIndx += lineSize;% @6 Z4 Z+ C0 C, v: ^- G0 \& G* Q* m
- } while (curChar != '%');
7 @: e1 B: H1 Q8 Q - _vm->_globals->freeMemory(decryptBuf);9 S9 @/ E9 K% M5 p% Y
- return lineCount;9 Y& _! g4 \; p4 F
- }
复制代码 " k& Z$ H1 X& q4 |$ c
+ U/ N, f7 Y4 G- n5 \! r |