本帖最后由 shane007 于 2023-8-12 09:10 编辑
/ }5 M9 h* V& ^$ G
2 R/ |# } U# I' [# Z& _$ y8 ~ 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。9 }7 b5 `- b _3 X
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
; E* F2 c0 c% Q! q
" O8 K f* x \9 r2 u( y 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。5 o: Y) E3 Y8 ^: g& p7 L' V8 [" D
RUEAN.IND0 z$ D8 {$ a- L. W7 ?
ruean.Txt
) Y9 |. U7 L+ M% p4 W4 j) M' L7 K$ Q+ J- b; [! `* K0 ]
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
% c" q$ t G8 t 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
( @* P* @. ~% X1 a* |5 [3 r! m5 |& c0 X
# {9 }: E/ r* ?! ]7 Q. ? *.TXT的解密代码如下
1 K9 J& t" c( C* Z3 h/ I- int TalkManager::countBoxLines(int idx, const Common::String &file) {
8 w( l$ @& R6 w! x5 x+ P - _vm->_fontMan->_fontFixedWidth = 11;
; l+ I/ N; ]7 N4 A, E+ N. Q
- P3 S5 `/ Y/ W1 O3 _- // Build up the filename
1 F/ _3 z$ ^2 k$ d4 i( Y - Common::String filename;
- x/ r9 z, L( z8 S1 d - Common::String dest;3 N8 I' R5 g |8 n' D( Z
- filename = dest = file;
0 v% Z( N% @; }" C - while (filename.lastChar() != '.')8 R7 s H1 ?% X' b
- filename.deleteLastChar();
' G B( ]+ z! h8 U# c. I - filename += "IND";3 X0 Y2 }/ r6 c" [: e! [
- $ ~: g2 X$ d/ s0 a: C9 A
- Common::File f;1 l7 q w* M V7 i# e
- if (!f.open(filename))
6 h4 G- r7 ~% v" O! }( v - error("Could not open file - %s", filename.c_str());5 s) G0 O V# J+ ?0 | n
- int filesize = f.size();& ^5 k3 D( N. l0 ?0 v l8 ~3 V2 V5 g
- assert(filesize < 16188);. R$ P$ C6 z* i. u( s
- 9 D$ L6 _& X# i( S; W' o
- uint32 indexData[4047];3 X4 w- }8 C% T
- for (int i = 0; i < (filesize / 4); ++i)+ W/ C s( C5 P3 ?2 d2 S
- indexData[i] = f.readUint32LE();
! v6 Q) w* Q, C; {. i - f.close();/ @6 D7 i, Y0 o8 i1 f0 a$ k
- . I+ W+ K4 c6 X4 N6 g( Q/ t" T
- if (!f.open(dest))
5 Q9 j* s& s H$ Q& w# c - error("Error opening file - %s", dest.c_str());
+ G" N/ k# R/ x2 }$ h- Q
0 {: ?( w# j D- v. `- f.seek(indexData[idx]);
0 L! M2 h) L5 h- t - byte *decryptBuf = _vm->_globals->allocMemory(2058);
* R) Q: |! a/ K/ s7 e7 X - assert(decryptBuf);
! i* }6 o7 }8 [" Y3 _5 G3 t - 2 }2 t; z7 V. g V. c
- f.read(decryptBuf, 2048);* C: r* m6 q8 B4 J
- f.close();
; e& ^+ C: V! t1 `0 l! W4 j - : z; I9 q" X& a" c: H' `! n. l+ s
- // Decrypt buffer. O$ h# a6 C1 L5 r- D$ K
- byte *curDecryptPtr = decryptBuf;
" q% e ~% W U9 V - for (int i = 0; i < 2048; i++) {# u! {0 Q, o$ R6 E
- char curByte = *curDecryptPtr;
; c+ I' Y" X1 u9 B* } - if ((byte)(curByte + 46) > 27) {0 h, T, j( y- `/ `
- if ((byte)(curByte + 80) > 27) {
( J: C/ ]5 A2 i - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))) p5 h; \& N3 a% |7 ]7 h
- curByte = ' ';/ D, l" {+ m3 M3 i {
- } else {; G: y3 q/ H8 [7 C* T9 s
- curByte -= 79;
% W8 e5 `2 f- {: t - }
: R: O' }3 Y2 f1 M* V2 P/ \ - } else {* g: G2 d3 x% s3 l
- curByte += 111;7 F% B8 G: `" j# E: d# D
- }
, E; X( I' B- s2 ^ b7 t8 p% @ - *curDecryptPtr = curByte;
9 A; \' j% c! h/ U - curDecryptPtr++;+ V8 Q7 K7 {4 B
- }
) x' c' r) E& w8 C' r - + c/ v: W" }/ S/ x
- // Separate strings+ S# b9 E0 ^2 W( b5 ]
- for (int i = 0; i < 2048; i++) {, ^2 v1 r" j: H9 g5 J# H9 l0 L
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)+ x5 X; \/ I7 f- T- u, M2 V w8 i5 F
- decryptBuf[i] = 0;
' I x. U- y! J q b2 T - }+ g+ o/ z. n6 a4 o0 o1 `: m) P
5 T7 r- K) h4 F' w5 I- ?- //add by shane007
; U* f- {5 Z! B) q1 r - //debug((const char *)decryptBuf);8 ]7 n9 N3 m+ y# Y
) a6 w9 b) m/ t# O- // Check size of each strings in order to compute box width& N' }0 S3 C6 j+ g; d
- int curBufIndx = 0;
# T# O: i3 C; \* k" @: ^) | - int lineCount = 0;
0 o4 E" d- B4 U+ V* f1 k Z - int lineSize = 0;' y! ~+ \" N/ o! t& ?
- char curChar;& p- z$ H/ V0 Z- E
- do {
0 [+ e( b5 k* j6 s2 b. x - int curLineSize = 0;
6 l4 \( U( ^1 N: { G - for (;;) {
. ^' f, t2 c9 {7 n0 l4 |5 ` - lineSize = curLineSize;+ j( E6 u* y; P' d& C
- do {
# n. U0 {& c' c - curChar = decryptBuf[curBufIndx + curLineSize];
2 T$ b* S8 U! j# M! v& I - ++curLineSize;
: ~# |9 Y7 Q4 b7 g6 a - } while (curChar != ' ' && curChar != '%');- `$ p) h( }" m7 T' d3 v. C& S
9 d: n" k4 o6 N" l2 D- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
9 Z2 h' x+ e ~/ }' l - if (curChar == '%')) t+ S6 k" X9 H, [' ]# ~/ j, h
- curChar = ' ';
3 N" f. e( h6 s4 i& z6 S1 q R - break;6 {% N9 L% r' E5 l& x8 ~2 k
- }( k; A5 f+ A7 X% Y# @
- # X" r3 N! h) g* L7 R9 e* I) v5 `
- if (curChar == '%') {' J+ l- g/ Z1 _7 C' ]5 Y! }
- lineSize = curLineSize;& [5 _+ |8 U) j2 W6 `# q# O
- break;
( q3 g9 C5 H- }; q% { - }' `: d' o( L2 G
- }
& ^! `" B0 h7 o* `; ?, e) P( Y - ++lineCount;' F3 Y7 h) K* v; U# d5 X) g0 g, V; y
- curBufIndx += lineSize;
1 B2 D: n' \# u, l - } while (curChar != '%');
% u2 d# ]: `6 l- x. X/ G - _vm->_globals->freeMemory(decryptBuf);9 c7 S- A' v5 ]. |
- return lineCount;+ F. I8 ^# L, q+ j6 a, X
- }
复制代码 + Q& E& l9 l1 o) H& I
5 {. T3 s5 J$ y* d) ^ |