本帖最后由 shane007 于 2023-8-12 09:10 编辑 ) X7 X* \- k# e; j2 ]) k9 p. l
9 u: P; b' F& e9 y
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
! z2 V+ k6 T; q5 N$ a6 O! |9 r( ` 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
3 L+ r$ X2 Y) d+ P
: O7 f' g' n/ }( K& ~; m' t 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
6 N6 W i+ W* ?6 U RUEAN.IND6 y& K# O. ?, C' U. ?5 w+ e0 B- [
ruean.Txt
" F5 ?% _- l8 }3 e
# W' c: L& y# }2 E- M7 C7 N% T *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
$ }8 f [: b$ N2 l9 X8 u- p- ` 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
6 q, n! f, D; e" ?( |+ x% @* ?4 A& X& I2 m( T6 b
1 j J# p# y/ x, z N *.TXT的解密代码如下$ F# A# t4 S' {1 s R* x
- int TalkManager::countBoxLines(int idx, const Common::String &file) {
9 U& E, l6 h2 ^1 R5 ? - _vm->_fontMan->_fontFixedWidth = 11;) e, _4 R- a" C2 a5 ]! B" U0 O$ d
" d; j) C" i |$ `. f" n% Q- // Build up the filename
k# M' |& n1 Q, l2 } - Common::String filename;
: D' d1 Q4 k& m+ u - Common::String dest;
1 v* B7 ]/ R' H r3 y' Z - filename = dest = file;
" j. q2 x2 @ d, A0 P - while (filename.lastChar() != '.'); p& s4 S5 B& _, ]
- filename.deleteLastChar();
, k$ j" t! i: j7 I+ ^ - filename += "IND";
& a# o% O/ x! a2 z
* p; Y* h2 |" z- I& N- Common::File f;" s( C6 m5 {5 i: ~- U, c1 n z
- if (!f.open(filename)). K7 N/ \/ \; z! O* T; s
- error("Could not open file - %s", filename.c_str());7 ]3 K5 S/ w) F
- int filesize = f.size();
W; ]1 }* c8 J0 F7 _ - assert(filesize < 16188);
/ S" G- A, d, f - 5 d5 {, m5 d5 x* J: v
- uint32 indexData[4047];% x7 a6 A0 q/ m2 t6 z* f
- for (int i = 0; i < (filesize / 4); ++i)5 g$ x5 ]) {3 r2 I
- indexData[i] = f.readUint32LE();7 f5 `' U. ? W7 ]! p( B
- f.close();
9 f* M. y& |' b) } - # X0 f0 N0 B$ v! g
- if (!f.open(dest))3 o( f8 m, \% _- o: m4 r9 }
- error("Error opening file - %s", dest.c_str());
8 z g3 w3 R- V7 t - . s( W3 O' [, e- N
- f.seek(indexData[idx]);
1 q4 h/ K# w8 Q1 @7 \ - byte *decryptBuf = _vm->_globals->allocMemory(2058);
4 ?) v( a1 \6 P2 Q9 a - assert(decryptBuf);
! o8 M% R# Z6 y
$ x! k3 f3 w% ]1 ?% O% `6 u- f.read(decryptBuf, 2048);
$ R3 p) `+ A) M- b" H+ y6 Y( ?5 } - f.close();
. c; {4 ]1 h9 E
/ Z, X ~( }$ m- L% t* }$ f- // Decrypt buffer# M; ?" G x4 Y5 J5 M
- byte *curDecryptPtr = decryptBuf;! Y& d6 }. I, J% l" H! [
- for (int i = 0; i < 2048; i++) {
9 B% w# L: R$ `+ S! ]+ t - char curByte = *curDecryptPtr;9 q. u2 J- [7 k+ F* M( ?; }! f7 c
- if ((byte)(curByte + 46) > 27) {' W5 {, E( B5 O# T
- if ((byte)(curByte + 80) > 27) {
, f9 n& M$ G, _5 `5 y' H/ l! ^$ y; ^ - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))( O$ f! h9 W ^/ V* e4 W e
- curByte = ' ';0 d/ e6 F5 a' }: v4 j: }
- } else {' m n1 N4 L, C+ d# g2 t. @
- curByte -= 79;6 q2 _2 f# b: \
- }! _2 Q2 P+ S- }3 c8 Q U/ `2 {" p
- } else {% T3 Y) `/ o" G. [
- curByte += 111;, I. |" E' m/ J9 l5 s
- }8 G: ~" ]2 F8 G6 P( ?
- *curDecryptPtr = curByte;. P7 i6 N# o' ~6 a. {/ n; ^( Y1 B
- curDecryptPtr++;
3 j* @9 W4 B# b, m6 q) z - }
* v! @- T% D2 A9 J - 3 S, k4 N9 X6 q1 |$ C9 @# K
- // Separate strings0 l [$ f9 U" d
- for (int i = 0; i < 2048; i++) {
0 d2 B' y8 J' C0 a" P4 `) [6 g3 o8 R - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
0 Y" A+ @; l L: e- h - decryptBuf[i] = 0;
, t# P+ |& }/ |! c S! e - }
5 ^* ~) P3 G( E5 F - 0 v: C2 b$ G6 V& m# O, I
- //add by shane007
1 @& n6 x0 B4 T, Z - //debug((const char *)decryptBuf);3 w9 d4 J% P5 j( _( o) X- C$ l
0 x& ]" _/ u4 e, @& }4 }- // Check size of each strings in order to compute box width# M$ V0 R2 j4 F4 {3 H. x& K
- int curBufIndx = 0;
9 A8 ?" {, m2 s$ P9 V. V5 P - int lineCount = 0;0 t( ?* Q3 D7 V# i: h+ e$ {
- int lineSize = 0;
/ ^( } b+ h8 C) ^0 \ - char curChar;8 l: l C- S/ Y/ i
- do {$ m& x* i ~# G! V% J% O
- int curLineSize = 0;
+ u! o8 [& d5 F- } - for (;;) {' K8 b: q( P2 }# [/ _8 @
- lineSize = curLineSize;/ Q* G( I; O0 t4 h- l% t
- do { R" t2 ]7 s9 q% b4 i/ S9 `
- curChar = decryptBuf[curBufIndx + curLineSize];
* {) I+ D5 \6 [ T" N: C( F - ++curLineSize;. Z2 C1 y! H4 F& x4 K ^
- } while (curChar != ' ' && curChar != '%');
* _4 V7 ]0 y" Z( G1 b& B! g; e/ E - ' L4 p7 X7 }" o' g5 U9 l
- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {, w6 B* ^( O( w1 I g& g3 T4 x
- if (curChar == '%')" X/ s# a! V; _ u7 }/ Y3 D
- curChar = ' ';5 ^8 g" }' q5 h
- break;, l( T4 a3 b* H* l1 u& D
- }, l( j8 @- ~2 I9 A2 |* R
- ( x9 l/ r% }- B9 g5 c: }
- if (curChar == '%') {
0 S* U+ @" J% R3 q - lineSize = curLineSize;
4 u9 h: N @2 k8 l' V0 b8 Y) R - break;
. b' G- T, ~% V$ C - }$ Y8 m/ d6 h' } d
- }( Q0 b( `- h# t
- ++lineCount;4 X3 N: o D7 b
- curBufIndx += lineSize;% c2 z' c9 ~3 ~
- } while (curChar != '%');
( P/ G6 b. N$ h/ g. @0 t( _' ?: ? - _vm->_globals->freeMemory(decryptBuf);
3 U/ G# q% ?8 ]' G - return lineCount;5 B2 }- a- T0 e7 q1 o' o
- }
复制代码
$ ]4 c0 B; w% g; M1 t8 y) a4 F+ v' ?; `. ^7 d* b5 R% K
|