本帖最后由 shane007 于 2023-8-12 09:10 编辑 - G4 C7 R) a' E5 c" |
4 x. l( A' l8 Z- b 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。3 k- d- a) d) H0 `, f
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。6 O7 o1 _3 U; I& c5 O
$ v+ p) K' I" v8 Y1 E4 n( i: ] 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
8 [6 q8 z- M) _% r M5 \0 ~ RUEAN.IND' \& H+ o; m! P" c$ ~
ruean.Txt9 F+ C8 x/ D+ g
0 J( C: W) }) Q4 v2 b
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
; B }+ f Y9 Y; S; \. F 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
- S, g8 |6 [/ N' ?; d2 Y2 t4 p8 a4 z, p/ t k' g# K% [) m3 t
' d7 {- `6 V. k* h( k' R *.TXT的解密代码如下
9 n, q# _/ R* g- int TalkManager::countBoxLines(int idx, const Common::String &file) {4 c3 B/ e: U" o3 i3 M' r% V
- _vm->_fontMan->_fontFixedWidth = 11;
& v; d! t/ f) b* E% f - : v8 Y; ]& N6 |, g6 I& x
- // Build up the filename9 h: s1 z5 q) n2 H. U {! ^
- Common::String filename;5 y* x$ E; U. I) V5 q
- Common::String dest;
6 Y, H" f5 @. j: t) L. A - filename = dest = file;
$ L" R5 a4 j( Q5 H4 b( W - while (filename.lastChar() != '.')9 G! [* \- t& n( N9 ^- p
- filename.deleteLastChar();
! _$ L F- d7 w1 W: T4 z - filename += "IND";
5 _1 r+ u! q, o0 v9 P4 q6 d, Q
( E& w& d% O. Z% m5 i1 R2 J- Common::File f;) w. }2 I! t6 p* c+ c- B
- if (!f.open(filename))) D" F: j; I1 U, t. A
- error("Could not open file - %s", filename.c_str());
1 M& I& R6 ?- o0 W1 r - int filesize = f.size();
6 f" L$ c) T' y' w3 ?" @ - assert(filesize < 16188);
( K; p* W1 l5 Y1 ^ x - 5 H" K2 w' v7 _& W' k- Z5 ~% A
- uint32 indexData[4047];1 E& h* g) r' W! V5 ] B
- for (int i = 0; i < (filesize / 4); ++i)
4 J; c- `+ y7 `6 S0 _ - indexData[i] = f.readUint32LE();
. g- p# V+ W7 Z5 A - f.close(); N' T# g! ]$ A: r8 @6 I
- 9 P* `' p' o N% e% F
- if (!f.open(dest))
1 ^$ w2 r/ y+ M1 Y - error("Error opening file - %s", dest.c_str());& g$ Z5 i: o! n h/ C
& _. a9 v# {- R- f.seek(indexData[idx]);
& Q- r' \7 G' B, J$ p I; | - byte *decryptBuf = _vm->_globals->allocMemory(2058);! [, {3 R& ^# ^. [$ W0 W
- assert(decryptBuf);1 I- A L( c# z
- 8 w; e o" X. Y
- f.read(decryptBuf, 2048);( f/ E( ^; x& W p
- f.close();- E* p( R, p, M' ]2 E' x
- " L( s! Y6 u4 V$ M7 Z
- // Decrypt buffer* x: o' U9 c1 S, @9 E
- byte *curDecryptPtr = decryptBuf;
5 g: s) x; n% v8 \' x) B - for (int i = 0; i < 2048; i++) {
( F( b/ q2 L! ` U - char curByte = *curDecryptPtr;" c6 l" E- W. o B. d9 g# g" Y
- if ((byte)(curByte + 46) > 27) {
4 E/ N0 r- ?& {" b% R! P( r, A - if ((byte)(curByte + 80) > 27) {+ ~5 x2 U$ m3 ]1 [
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))5 Q- ^% A+ A/ ]3 v
- curByte = ' ';; `. u/ M" Q7 ^2 k8 f
- } else {5 c# n, e9 y& d2 u7 x
- curByte -= 79;3 A$ p4 v& \. w) d, ] H: b
- }+ r+ T" g5 N- z* @, ~( Q
- } else {
( R6 t" a' A' z - curByte += 111;& [+ D0 q9 O: @8 Z, ]$ Y
- }4 I; L/ Z/ F4 s% {2 a! o$ S: H/ u
- *curDecryptPtr = curByte;) H3 L4 m- s5 Q" G' i6 s6 O
- curDecryptPtr++;3 ?3 Q, {! L( f; R6 }
- }
9 I# }2 p7 {) X6 e' Q# c
; ?# z$ {$ B) B- // Separate strings
$ C# r3 L* c2 v1 K0 k - for (int i = 0; i < 2048; i++) {
! ]4 j* y# y) b" n; W, E - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13) y* a, }# T! R6 q; {
- decryptBuf[i] = 0;
" B6 ~6 ?/ v$ I - }1 G) ~; T7 E2 f h8 L; h4 J
% f( z6 e* W2 E) _0 u) N- //add by shane007
2 K; q* w. D% v' X6 c: t* w2 ^ - //debug((const char *)decryptBuf);' ^7 o0 T: G9 O z4 X
8 R9 U$ g, {- h# P g- // Check size of each strings in order to compute box width! {' Y1 k6 F Z" h& [
- int curBufIndx = 0;
* ~* j) `8 a! a: _9 n& C4 b$ ?8 x - int lineCount = 0;. ]$ z% ?% o, n& j1 _
- int lineSize = 0;
9 p2 V# o6 I' a0 j" `4 u - char curChar;
: O. S9 p' v! h: q( O - do {9 N/ f7 v6 ^. F* |' z
- int curLineSize = 0;* B7 W/ S: B0 q
- for (;;) {. n. K; y0 o6 h- o/ T5 ]
- lineSize = curLineSize;* j8 E3 Z1 E: l3 M% ?2 d
- do {& P8 `$ @/ y( e5 D' [; J4 R
- curChar = decryptBuf[curBufIndx + curLineSize];
2 O% \( }# h5 v# P# [. D; z3 v - ++curLineSize;
/ S- a+ A4 X; }* F1 x. [( j - } while (curChar != ' ' && curChar != '%');& z9 {' d% n+ R$ A9 q0 L1 E, C
7 X& Z0 _ ]3 H0 p+ X- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
- O& D! }- l. [0 e" ?& Q+ s - if (curChar == '%')
8 T. J6 t* g4 s - curChar = ' ';, o1 W1 P6 K ?# @* m" Y+ {
- break;8 }# g' d7 d7 v7 \' x
- }
. E# h ` U7 e% L: s3 k+ o5 c/ o
! F. V; M4 s o8 D, W3 _+ i- if (curChar == '%') {
1 h$ D5 t7 d" x9 h, X" P - lineSize = curLineSize;
& T. s: \9 ] l2 U - break;
. j1 b4 ^9 z/ D% n$ y* Z& P% M - }
( q8 C; x9 X% Z' {/ h+ Y - }( n W ?5 n5 u7 M
- ++lineCount;
! h9 s+ q: w. m, b# }3 ?* Z6 N - curBufIndx += lineSize;
! K, X) ]' T6 |0 w8 g - } while (curChar != '%');
, }- m7 f- h0 h3 }7 ` - _vm->_globals->freeMemory(decryptBuf);
0 h0 h ]3 ]6 w! ~+ I - return lineCount;
$ [9 @' l* x! q( _1 G) ], d4 B9 N - }
复制代码 2 M, P4 e. Q6 Y, w, J8 s+ Q
2 W9 X0 g6 q: f6 _ |