本帖最后由 shane007 于 2023-8-12 09:10 编辑
7 M2 j: L: ]$ f1 H, B5 n% _$ X" S% K
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
3 |* i) h% r* _/ q 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。$ I2 w/ Q1 F, E. @8 p3 f
( V8 W; g+ Z# H) L2 ?& ?' d% \; K 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。- _. Q5 ^/ C4 H. I- K0 [8 h+ R
RUEAN.IND
" j. G0 I7 t; a: k( ~5 I3 A ruean.Txt3 |: D! i9 S& O( Y% |3 F
2 G" i2 M! o. |4 I
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。- `4 B, _0 h6 i* \: u- [
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
& `1 s) d4 x& ?) B, e0 ?+ ^% Q0 L* x# I. A( W, I# t. ?
1 b @: m) B6 W7 I9 F% I
*.TXT的解密代码如下) k# h7 G6 \! [. P8 Q. K
- int TalkManager::countBoxLines(int idx, const Common::String &file) {
6 c" Q/ O; ^7 \7 ` - _vm->_fontMan->_fontFixedWidth = 11;
# i( f* ~" |* a( e' e( o* e: n, ` - ! K% n! Z( B }* Y6 P6 U4 Y
- // Build up the filename( @3 @. R; Q9 y; I$ m. k
- Common::String filename;' ?( { d) j: }
- Common::String dest;' r, f" ^9 {" v; m
- filename = dest = file;3 F2 [" L- ^) j) f S
- while (filename.lastChar() != '.')
& U, y' [, `5 p2 v - filename.deleteLastChar();
( U, l m# M3 r& D' m8 E7 u, } - filename += "IND";/ f/ A! V9 t( n
- + T: r: k. I1 I1 e* m
- Common::File f;7 l& J. C0 |' W/ w
- if (!f.open(filename))
9 b x7 D; |) n, \& u - error("Could not open file - %s", filename.c_str());
- S5 Z0 A( n, c- e8 W% {, ] - int filesize = f.size();
& m) A/ c7 V0 [3 i2 z4 k1 B - assert(filesize < 16188);0 q. r3 c6 \% @/ f4 q X5 f7 d2 [
- % A) H+ q8 t0 H* W S" L
- uint32 indexData[4047];
# B- T5 X* l+ L5 O. {" R0 ^" {6 U - for (int i = 0; i < (filesize / 4); ++i)3 i- G/ [2 o( i; f
- indexData[i] = f.readUint32LE();) H0 W$ g+ q$ }- i+ d
- f.close();1 M/ I! c! w5 t' ^, M; K M5 q' w
/ \0 c- I1 o/ i# j0 D# G- if (!f.open(dest))4 j0 l3 [& K/ X, o/ g, p4 f
- error("Error opening file - %s", dest.c_str());
/ n, r& n. L8 L
; B/ X: y! G3 Y, l- f.seek(indexData[idx]);
+ M9 L& z# H( S* l9 m! ?1 n - byte *decryptBuf = _vm->_globals->allocMemory(2058);# S: e8 r W7 Q0 V" E9 R# J
- assert(decryptBuf);
% J8 p3 i! U" a. V
0 Q' [7 }+ t% l/ W- f.read(decryptBuf, 2048);
1 W7 Y$ R! J( s! }, `3 x - f.close();
4 f( l: L# G& Q5 {: \7 B) a$ g6 H - 7 ^ d3 C7 g/ ^9 P7 h3 u- {, d
- // Decrypt buffer" \0 O( ~6 d. p; L8 Y7 p
- byte *curDecryptPtr = decryptBuf;6 j. o4 o2 r& K
- for (int i = 0; i < 2048; i++) {
. a$ h" @/ s0 y* z7 F0 Q$ S/ s( J/ w - char curByte = *curDecryptPtr;
! x" x9 M K+ ]& o6 x/ Z - if ((byte)(curByte + 46) > 27) {6 u9 G3 D, v8 H* b% j
- if ((byte)(curByte + 80) > 27) {
0 U: e6 a! }7 \ - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
+ M. d' A; g. _: Y( V5 }1 ] - curByte = ' ';
1 S$ J6 k) J* Q! i5 H- ~7 v - } else {( _# M2 h7 E( ]2 i7 I2 r
- curByte -= 79;
- {1 h8 D- h2 C5 A3 X7 @2 C - }
# L9 n# r, S! h; r - } else {2 K/ ~/ L2 l0 W; N; i) Y8 ?
- curByte += 111;
( V6 ]# A5 C& @' O - }+ T4 V. B9 t+ H; F. |' |! @$ \
- *curDecryptPtr = curByte;
$ e3 W: F5 S# q0 r1 h( O y8 V/ j0 E - curDecryptPtr++;/ c) T3 Y, |+ C% f) a& l
- }
" F3 O, C# f# ]4 u8 x+ d - 6 g2 f1 G5 A8 E, X3 n4 |
- // Separate strings$ u- L" G, D3 F& x2 l( o2 r3 D
- for (int i = 0; i < 2048; i++) {- C! p! V$ g5 D0 O5 W
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13) d3 k' y! n6 x0 ?& Z
- decryptBuf[i] = 0;9 e/ h2 t3 F* T. A) @. Z
- }
0 V6 d/ U) I, Q" x( q - ! i' d/ o' ~8 Z* O/ M8 K
- //add by shane007
- q1 h5 { y/ [" f! q w1 H - //debug((const char *)decryptBuf);6 |7 j2 Y v7 D
- : m. C, ~* h% W _, Q
- // Check size of each strings in order to compute box width
3 u O5 ?( O8 D( g) \+ S/ A - int curBufIndx = 0;
2 _5 @) g9 J8 w# O5 V; `# z - int lineCount = 0;9 H" ?: r/ ^3 X( N; w) k
- int lineSize = 0;3 o$ K5 F. P) u$ Q0 d
- char curChar;& s, b3 \4 m) L" E" c* H5 M
- do {
0 e3 ^' }6 ]( g' f+ |: E% Y - int curLineSize = 0;% N) Q$ t" J; {+ W C/ `- ?9 ]$ e
- for (;;) {
$ c8 |4 v' Q8 D - lineSize = curLineSize;% S. C" I% P) n" V2 }0 _1 o: k. O
- do {
+ {7 |$ z* e" Q: Z" V! E - curChar = decryptBuf[curBufIndx + curLineSize];( d% s. R, c y" T& R# D
- ++curLineSize;' e% S+ ]6 N0 G' `- \- t6 T# I2 W
- } while (curChar != ' ' && curChar != '%');& F' k* I0 S& p3 L) O
: t9 i' [9 Y. s9 o$ I" w9 y$ M- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
: {7 S. { B7 a" J - if (curChar == '%')$ l- p% D& p. Z- k
- curChar = ' ';3 Q& m" i' l' S- K# Y
- break;
& }) ~; E( V2 S1 z; g/ H# ~ - }
4 K* J, B( u9 w) A. ^8 L/ j( g - 0 F+ P6 ] {, S W
- if (curChar == '%') {8 I: t6 F' ^9 n* h
- lineSize = curLineSize;$ K8 y8 _! D1 J3 D
- break;$ o6 f( [$ ~( F, x+ x' F0 w
- }8 R: I3 N) ^) O' Z
- }' }. l9 X) m/ q4 D* s# |
- ++lineCount;
( q; ]5 ?0 C' k( J5 K) t; j A - curBufIndx += lineSize;
7 X1 k& T" n3 K" ]' q) u - } while (curChar != '%');
, m1 A9 ~. l0 _$ Z! ] - _vm->_globals->freeMemory(decryptBuf);$ U6 @/ G4 N1 R" U8 a: S! X
- return lineCount;0 W. V1 d6 ]( b5 `
- }
复制代码
) E a6 X* \6 M! Z: ?0 G0 g3 ]0 P/ Y' X. ~
|