本帖最后由 shane007 于 2023-8-12 09:10 编辑 : S/ b( x/ v8 F+ j X& ~
1 o/ Q, Y' d3 f ^
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
$ R: \" ]" k2 Y 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。1 [# c6 H6 a/ n5 R+ e* P
3 m8 Q/ O! }0 Q3 f) \+ `
比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
2 M. M% i0 ?7 O, Q8 S' E RUEAN.IND9 Y) ~* @, y1 p3 s; c. E+ u
ruean.Txt. b) u/ t5 f) ^& k& g2 E3 p) N: F
% I8 Y9 j: @ [$ s! `( }1 u& u0 I4 o/ G
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。1 g1 Q: h, u8 g9 H; @* X0 e# f
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。# ^" S& w0 D% b. P! |+ ]
' c9 l2 P5 h7 x( Q9 w& O* N1 J' c% f! G
*.TXT的解密代码如下
% i: t7 `' v) L9 C6 x5 ~- int TalkManager::countBoxLines(int idx, const Common::String &file) {3 J, m2 [# n3 @3 w$ |, X1 z1 S
- _vm->_fontMan->_fontFixedWidth = 11;5 ~/ m/ _4 ]& G* R; {
- 3 X/ P; @2 o9 B% k- d5 S
- // Build up the filename
6 f' U1 X' s) l6 q" i: h1 B - Common::String filename;
: o! @8 k; y3 O7 G; x$ Y - Common::String dest;0 ?$ S; {- F( p6 S' k3 I8 y
- filename = dest = file;
7 r$ s. D# Q4 g5 Y+ r' g - while (filename.lastChar() != '.')! M6 t# D3 o/ J5 K& F' {
- filename.deleteLastChar();" ~( k; D( y5 r5 p
- filename += "IND";( _" B, \9 H v: C8 M
* @- g+ F$ I8 k! O/ y- Common::File f;
& I- z* i* [2 O" m) h { - if (!f.open(filename))
- e; e8 U) |9 k7 n0 F2 v - error("Could not open file - %s", filename.c_str());* [- W2 {0 ^/ x" f: E% t
- int filesize = f.size();
" U4 h1 @3 @" U( W - assert(filesize < 16188);1 O* c$ t5 r" Z" R* [1 Y
% ~5 m) b0 {8 \, |6 j) O# b- uint32 indexData[4047];
* ^ Q" z: ~2 ?5 {3 N1 r7 M - for (int i = 0; i < (filesize / 4); ++i)# ?: i5 A8 K6 a* e R
- indexData[i] = f.readUint32LE();! m0 b- R. f( b+ b+ ^
- f.close();
1 K8 l. T- E8 o" Y( I2 |" u# m7 N
, \1 a5 X+ m' Y2 ~8 Q) l4 r- if (!f.open(dest))
1 b1 U9 g+ q! W4 N0 P - error("Error opening file - %s", dest.c_str());. K$ _$ P' A" M; b# x- b2 t
- $ [5 w4 [! u! U/ `, _% y6 p' V
- f.seek(indexData[idx]);( ^6 z( i1 |5 w0 A; \
- byte *decryptBuf = _vm->_globals->allocMemory(2058);4 w3 F4 p) R3 h
- assert(decryptBuf);
! |! C: X% b3 S% N - , n7 A% X+ ~3 c% Z' Q
- f.read(decryptBuf, 2048);8 S8 `0 N0 W; _: O9 U! z( z
- f.close();
9 u( i* W( R. ]" j - / K% X" O0 G& m x. y( s7 Z
- // Decrypt buffer) U7 |2 D% m$ T" Z
- byte *curDecryptPtr = decryptBuf;
& E! R! r3 x _+ e6 ?* u J - for (int i = 0; i < 2048; i++) {; ` O. {4 B! S7 ^
- char curByte = *curDecryptPtr;+ K+ v9 E* O+ N' D+ a6 G
- if ((byte)(curByte + 46) > 27) {
. V/ w! ?1 n, |9 x) b - if ((byte)(curByte + 80) > 27) {
! y# l+ |& R) l5 ^$ M" c - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
" E$ S% W" a D0 y6 m( [9 V - curByte = ' ';/ L. c- R+ W- `& |: Z# P( S/ \
- } else {% j! q8 F! i/ M+ B% O$ e
- curByte -= 79;# `) I/ ^3 z1 D9 S4 f) ]( o$ _' L
- }
7 P. A5 A p; q5 x. [% f - } else {
. P5 J1 o: H, r5 E, R- O5 \) g - curByte += 111;) T7 ?: N q# U# K% G b4 A
- }' e9 g! b+ i# A- R* h' N0 `
- *curDecryptPtr = curByte;
& D9 I5 D5 `; h, z( D; l - curDecryptPtr++;
* y0 A) n# h, E0 s% n - }; X$ f) E7 A; B3 O( E" r
8 J3 t2 F( g( B" v/ }- // Separate strings9 q" V1 U5 q. g: L) z, B
- for (int i = 0; i < 2048; i++) {- \/ q+ w/ u/ V! w% S8 A
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
) J8 [6 W# X9 T) o2 M - decryptBuf[i] = 0;+ @( w3 g4 j7 U: ~
- }
& {/ d# E# w8 b+ z ^* K9 U, m, H
, L9 s3 i! x+ C7 P% T2 T- y# l- //add by shane007
_- O; H1 |$ Y) L2 z - //debug((const char *)decryptBuf);
. p+ \( K3 g% |% k
L1 A4 h/ I2 Q3 d" `- // Check size of each strings in order to compute box width0 d. L8 c3 W; U6 O J' x: \
- int curBufIndx = 0;8 E4 c0 y" a4 S9 {8 Y" O
- int lineCount = 0;! Q0 x& V% @( K: ]9 T
- int lineSize = 0;( J2 \/ G! r( u, c3 B( C) e- \
- char curChar;
& q% m% f. M/ t9 h: A - do {
' U9 J% a! C( H& j8 n - int curLineSize = 0;
; Q, u' X0 A, O: c" i" s - for (;;) {
7 L. n/ m) U# F! w( V3 @0 l. L - lineSize = curLineSize;
$ x; \4 E# y8 x. P( D - do {% Y" F9 O/ c a# ^8 a, z
- curChar = decryptBuf[curBufIndx + curLineSize];. r; d& v) p- E- @6 s
- ++curLineSize;
8 N' M* Q* P& j* B) w - } while (curChar != ' ' && curChar != '%');' @3 _% [; j9 \" _( {5 ^
- + e2 r* x- N3 g7 t
- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {% b% P( I9 j2 X5 ^: }1 j: N: O
- if (curChar == '%') |3 y& E6 m- m; H% M
- curChar = ' ';
( [6 V, L! n+ b" N: b% e; n - break;4 `- N( _% f, L% b/ F
- }. j: n/ ]% d q9 s1 {, f
- , I7 `; z! [/ z6 N
- if (curChar == '%') {$ J, \( {+ R% T3 b
- lineSize = curLineSize;
( |( ?: a- y$ z* Z- N - break;. j% K ?& H$ K
- }
$ I6 @" p+ o3 T* @" T7 V6 ~; s( {5 x* | - }, @3 i) `. ]/ }: [" V( s
- ++lineCount;
9 R# v$ E0 J+ V& M5 C - curBufIndx += lineSize;
+ Y6 G$ Z' i6 r, r5 n1 ]: O - } while (curChar != '%');
: E8 B5 {( ]- ?, T Q - _vm->_globals->freeMemory(decryptBuf);* P K6 d. f; B: I5 y
- return lineCount;
" b' n r5 E4 X* K1 x" t - }
复制代码
" Y9 ~5 z! y% U: u1 O. S
. ?( v2 k2 K/ V" V4 H$ k |