本帖最后由 shane007 于 2023-8-12 09:10 编辑
$ r! S% n* X# W, X0 Q0 ]6 L# ^( }
' M+ r/ g" |. F 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。1 Y3 @% F' y; Q& G
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
! d3 G& C: i5 a5 f9 t! _) F6 O7 A% C. l- f. ~+ i3 U; R
比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
5 K& s' m0 a! a2 g: y RUEAN.IND2 M: V1 j) X2 Z9 d+ ?
ruean.Txt/ _4 V, V( @) m0 {0 |
1 C3 U" c l, S- s7 ~ *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。9 L: x0 N2 T/ [, U# S' p; I! \
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。# t4 H. g- [' x& d! z: [
& f1 y( {4 W: s6 f1 Z
, N% H- Q5 U0 ^! S *.TXT的解密代码如下. E% W0 c+ U/ C( y
- int TalkManager::countBoxLines(int idx, const Common::String &file) {, P3 J8 P/ A/ `( K" a5 [( A
- _vm->_fontMan->_fontFixedWidth = 11;9 \' t7 a. Y- z5 Y @$ Q: p
$ N- R" x3 V/ y7 n \- // Build up the filename4 m3 f7 y' G% E6 M" Q8 q+ _
- Common::String filename;
& I& q/ q3 G. W9 B( C - Common::String dest;- j9 R+ Q7 o V
- filename = dest = file;1 x. `9 O- k" Z2 t
- while (filename.lastChar() != '.')
) _ o. P. E( @8 |% r! K- ~* s - filename.deleteLastChar();- }; t( r( z7 t6 y/ q0 @; Y4 W+ A
- filename += "IND";: C1 _- X1 S5 { P, g
: q# ]0 A# C: }/ Q [/ N4 f- Common::File f;
, u- {2 i' J) p) E" R: t - if (!f.open(filename))7 d- H7 s2 E3 y2 V% k% E
- error("Could not open file - %s", filename.c_str());
4 o; L" u+ t `! S* q0 t1 s - int filesize = f.size();
* s' G% F0 D% E* f a - assert(filesize < 16188);) A6 |* ^8 I ^, [; B7 c
- ) d+ k7 n8 U' y2 H5 W& o
- uint32 indexData[4047];
5 N W, z7 m& w4 a2 }0 p$ B5 A - for (int i = 0; i < (filesize / 4); ++i)
1 R, A: `. F5 A/ w - indexData[i] = f.readUint32LE();
* M" ]* [! S1 w3 e) P* T/ A; R8 X - f.close();
/ c. k. G6 N; T - * ?7 U7 o5 L8 f
- if (!f.open(dest))9 Z% }' F( k7 R3 Y" A
- error("Error opening file - %s", dest.c_str());% G9 _! X$ ]* G; B
- ; M2 Y/ N9 |/ ~8 D( T
- f.seek(indexData[idx]);
$ g0 O3 |9 @3 X1 A7 e' O: ~% Y - byte *decryptBuf = _vm->_globals->allocMemory(2058);% L R9 i1 Y& i! D8 q7 T
- assert(decryptBuf);3 v5 ~. s% |7 C: |1 d, F
2 z0 _, \- x6 z3 k! Q' o; e- f.read(decryptBuf, 2048);' J0 Y0 ], G# W6 ?; ]0 V4 q3 m
- f.close();$ [# n$ D. {6 ~& r8 U7 Z
* A' d2 e" m- _: T- // Decrypt buffer
! N5 C' m. `' F& r - byte *curDecryptPtr = decryptBuf;
" u, s5 ]5 C- O6 G/ h7 \, G2 V - for (int i = 0; i < 2048; i++) {+ W# ?* r! n2 T C. y* J) ~9 @3 ?+ a
- char curByte = *curDecryptPtr;7 u* {% J6 a- u3 z. { w
- if ((byte)(curByte + 46) > 27) {+ a3 i1 @" a2 b& n; y/ c
- if ((byte)(curByte + 80) > 27) {
; j* {7 r- m5 ^ - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
+ s* X* L. [& y - curByte = ' ';0 r# ]5 t2 `. j
- } else {
: @! e* }2 O4 c, o- I) n - curByte -= 79;6 X1 U1 S& u" p0 M# T+ a
- }3 K1 f% V' K. F+ B. v% l
- } else {
: O, S% x) d9 e* P1 _& `3 Y - curByte += 111;1 I) z- \" P" }
- }
8 q1 N* f7 m9 X8 D: W6 A - *curDecryptPtr = curByte;5 D1 r. S U/ w x
- curDecryptPtr++;
( v+ C- [* f- R1 H - }" R9 S2 y8 a: F, r X3 p* r
+ h3 E3 I, v2 F' ?2 J% A0 {- // Separate strings: |4 C0 r" j( m6 Q/ \$ a
- for (int i = 0; i < 2048; i++) {
7 ] c9 D; s: w$ F - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)5 k4 J2 M W5 F j4 X' e2 b9 C9 S+ f
- decryptBuf[i] = 0;
! N9 Y9 s5 Q) G* J; X+ Z; D - }% ^1 c; r" N5 s& m- e4 C) q, _
3 I, H' z' j8 v; g8 V' n9 s+ @& w- //add by shane007/ ~; ^5 O9 J: a, h# l9 j: ^* @
- //debug((const char *)decryptBuf);
' X; Y5 w+ m( b% C1 v- F! ?
) {8 T5 u b+ {+ {- // Check size of each strings in order to compute box width6 h6 t$ o) U5 m+ b
- int curBufIndx = 0;- K: s3 I- \2 Q0 W) U$ v1 O
- int lineCount = 0;
& H) y: E" P+ L* u, s - int lineSize = 0;
3 B* z2 p' k" w, T; O - char curChar;: s9 O9 a3 _/ y0 F
- do {
) V; ] e9 l- o! W% y" j a$ ` - int curLineSize = 0;8 g! G8 A1 Q! y* J
- for (;;) {. @8 j9 q2 e ]6 ]
- lineSize = curLineSize;3 G) R3 Q4 v: e. W h
- do {9 _/ k% M- t+ Q- p4 S
- curChar = decryptBuf[curBufIndx + curLineSize];
4 \( w( J6 O' Z3 D% I+ P# B - ++curLineSize;
5 `$ u+ E8 ^. ], C# Q# o2 M3 b - } while (curChar != ' ' && curChar != '%');
1 B" W; V, f" o( e. S2 |
2 Y& c3 `( a p0 U6 n- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
/ H- h( |: x8 u/ C6 A - if (curChar == '%')
- d( W, {# a6 X3 s- A - curChar = ' ';
X7 N: L7 s6 H3 S$ F2 p$ S- }; C - break;
/ z/ t# Q# a/ G1 q$ V3 N9 w+ ^$ M - }
2 D7 ^7 R' P8 v8 l0 Z% l+ k& n: b - : u8 k6 A S9 r( ]0 a
- if (curChar == '%') {+ A4 R' R$ F7 m8 t
- lineSize = curLineSize;6 S5 W3 d% E& ?9 W4 E0 d" |
- break;3 k% k" {- E7 U: w! U; m) @6 |% a% |
- }
5 S( C- U# X! p, v - }% J( Z5 U3 }/ n0 p' `
- ++lineCount;
6 ? [- t! y9 V; S- Y& M% z - curBufIndx += lineSize;( [' d: c+ m# ~2 |
- } while (curChar != '%');
3 f/ l2 u# E5 l% a/ {! B4 S- p - _vm->_globals->freeMemory(decryptBuf);* U W- y' J8 W
- return lineCount;& L8 T$ h4 Z7 K+ O; Q6 L
- }
复制代码 3 n: i: |, K4 `* v' V
Z$ d! P- A) H9 N- z
|