本帖最后由 shane007 于 2023-8-12 09:10 编辑 - f0 g: T: U/ u5 B$ K; r4 |
. r" M3 w. h) l3 T1 m5 o9 W/ t 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
' F4 o1 O/ F( x' k9 V { 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
' P. N* u. a: K2 N/ _' n
# n0 G N3 @7 M; m 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
" X1 A5 R! ~/ a2 j! S RUEAN.IND
& U6 i0 j" x% e' q1 m, b: P% j ruean.Txt( c' o+ T4 S5 R' @' K
. f2 W0 O {4 T" M" r b; U. A *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
; h: ~! A6 }; B; y: z8 ~ 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
/ l' X0 v. R6 F5 V+ d
8 D; `2 t, b1 r4 ~9 b, b8 Y2 e) _' ]; z! H9 r. [
*.TXT的解密代码如下
/ Y* b( g1 P9 g- int TalkManager::countBoxLines(int idx, const Common::String &file) {
; P1 Z7 B4 s0 B- b+ Q - _vm->_fontMan->_fontFixedWidth = 11;) e4 Y' z) o: @) E
- % D* [. I6 f- F" f
- // Build up the filename
6 I, c0 }8 `- P9 f6 l - Common::String filename;
/ O1 X7 H/ q* O6 Y& u+ [' a - Common::String dest;: I4 I8 U" Z0 ^" H0 _, o1 j
- filename = dest = file;
8 C- p: n5 A3 q4 ]# b6 G) x& e$ {' U! F - while (filename.lastChar() != '.')3 t& y; B, v) w5 o
- filename.deleteLastChar();
# _( s; M2 [$ ~0 r( q2 [5 s - filename += "IND";# z0 k7 C6 U" O0 U
, u! z1 K8 Z4 S- Common::File f;6 T$ \; q7 D) y
- if (!f.open(filename))
" l% C4 i; }- N( P3 P2 u - error("Could not open file - %s", filename.c_str());
" @) e$ S: V* h4 K - int filesize = f.size();; m" g/ n M9 I; {- ]
- assert(filesize < 16188);+ P5 \: d+ b2 F, {; g
- # ~. U1 {# X* Y8 I: m% T0 |2 C M
- uint32 indexData[4047];
9 ?! M+ ]9 T8 U/ j5 {8 w - for (int i = 0; i < (filesize / 4); ++i); h8 t6 c/ E5 b8 |4 s9 d+ `" c
- indexData[i] = f.readUint32LE();+ u" D1 ^. U. T5 i
- f.close();
3 J- R% B4 x5 ~# a
7 N6 D w7 F( F1 x7 U' i- if (!f.open(dest)) N" U( z" D+ J: O, v& e
- error("Error opening file - %s", dest.c_str());/ F0 c: F% P0 S6 J8 K
9 Z7 r/ N( v7 u- f.seek(indexData[idx]);: \$ d8 G& c0 F0 Z
- byte *decryptBuf = _vm->_globals->allocMemory(2058);' n1 d' {/ a5 l6 I& J
- assert(decryptBuf);
& E5 E. q) I; s- N
+ D. n$ h, g1 _- p8 t/ Y# ^$ b- f.read(decryptBuf, 2048);& m; }: ^8 _- b: Q0 k# _& b
- f.close();% B! b. t6 X/ Z6 B6 i+ W" h
& ?" S7 T$ c- c6 i2 E- // Decrypt buffer
8 h7 N# r# y, j# ^- J5 L" @- ? - byte *curDecryptPtr = decryptBuf;
7 W7 B! l, n% r$ ~2 K- P - for (int i = 0; i < 2048; i++) {
5 f8 P1 Z2 m, R - char curByte = *curDecryptPtr;) b" x, ^+ s$ a) B2 \8 x: i. e
- if ((byte)(curByte + 46) > 27) {
, C. L) D! l$ l! [6 r1 E2 H - if ((byte)(curByte + 80) > 27) {( ^" ~3 _' t9 d6 y) q
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))2 X% L' O0 C C+ m3 \$ _1 p# T
- curByte = ' ';) j+ ]; [6 K# a
- } else {
. w( g% A& ^1 l6 d9 W - curByte -= 79;7 A) A9 c- H, B. Q! S7 I" t% Z
- }: b+ S, y( \9 Y4 }' {
- } else {
# p; V" d2 ^5 E- F L4 T" S+ l - curByte += 111;
) z7 I! r f6 U7 i' U' k) I5 x - }
" F. z+ i# d! b - *curDecryptPtr = curByte;: e, R) c6 q& X0 b* W! o
- curDecryptPtr++;+ p) ]4 a. w( y
- }
7 M# a/ Q6 s: R/ U7 b: e - ( L9 H% z. D" ^; x* U
- // Separate strings5 m6 {& O4 n% V
- for (int i = 0; i < 2048; i++) {
! f- y$ ?$ d' q - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
' S! l ^5 z, H8 z# h5 c - decryptBuf[i] = 0;
$ m7 K B9 g6 F$ t - }
) ?* c7 j/ F# O# R7 o
# W7 a* r( u4 [+ \# s8 Y$ J n# _* @- //add by shane007- Z' [# G$ `0 f# \6 k g% I* z
- //debug((const char *)decryptBuf);
|2 u. C% |; V" O9 Y( K4 N
6 j& I" z& e) g( {' R7 r- // Check size of each strings in order to compute box width+ U4 f& o/ u4 n4 Z
- int curBufIndx = 0;
, G1 @) c3 s2 g9 M5 r2 y4 z - int lineCount = 0;1 x/ c% V/ e2 Q. Z" _& Q
- int lineSize = 0;
! m* i9 A7 g6 ?' Z4 U - char curChar;( i0 y+ M" q. a8 ?" o4 T, o9 ?
- do {/ _+ a4 q! n3 j) ?2 `3 r! Y0 }3 v
- int curLineSize = 0;- |- b- B, B! X4 V+ ~) O
- for (;;) {/ ? s7 k2 E! m# J' q( U
- lineSize = curLineSize;
/ C# E7 e# Z; K2 M - do {
& S' ~+ N1 I8 W+ u - curChar = decryptBuf[curBufIndx + curLineSize];9 D4 Y" x( u1 x& C' _4 |4 q7 l. ]
- ++curLineSize;) r, g% w) n( C% ~/ C
- } while (curChar != ' ' && curChar != '%');1 Y8 }. F7 [& p5 |* I
6 ]3 b/ m$ A$ F L4 A" {- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) { p9 y1 Q' y/ w; J5 a
- if (curChar == '%')
" k3 s4 ]; w; T. m0 { - curChar = ' ';
; _" y3 A& {# p2 c. h5 ] - break;8 U; \* U* L, S: w# K* a
- }0 z- O* u! M; M) L2 H
- ) F5 M2 w4 f6 S+ E2 S: \8 t' x
- if (curChar == '%') {
* h* J& G) o* F- z - lineSize = curLineSize;
8 |1 R3 L2 O2 f5 n* O* M. ~% a/ T - break;( E% B( B* R2 E& |9 E% x$ t
- }* H1 _5 f! I- {4 H" }/ J' a
- }1 r3 f( Z# h* j2 T6 u1 e
- ++lineCount;
+ L. g4 @( R3 M4 w - curBufIndx += lineSize;
$ Z1 O4 n* P6 d, Y5 S) j - } while (curChar != '%');
& U5 [3 h/ d) d7 H* x - _vm->_globals->freeMemory(decryptBuf);
2 b$ ]0 J# {4 w( f8 H- @4 Z( X* Q6 n - return lineCount;
9 l. _4 V) J$ A8 y+ P9 [/ s - }
复制代码
5 V9 t* `# _8 ^/ |4 U
# |1 w; r% | V+ m( {) ~ |