本帖最后由 shane007 于 2023-8-12 09:10 编辑
5 z& d9 N) ]( n8 w7 U: g1 [) i: n7 C* m( S5 n- J8 v
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
9 v8 y( y6 _- }" W2 d 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。# t) B, d9 P: a9 ?
# R$ U0 Q; i! Q" I: M1 C
比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。& p* k) d, k& y; ]
RUEAN.IND \; J0 L3 U% S. j# c
ruean.Txt
4 j0 @, C0 M5 p6 o0 u8 w; S: @: } s1 G7 t- _% A C% K
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。- e) Y& d5 i4 ]' c5 A' V' s3 q' ~
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。$ D* h' R# ~; q1 j1 a$ ~8 d
! C% m- s. W# P5 ?* X# e" N2 w
E% R g1 l( g1 F
*.TXT的解密代码如下
; n Z1 j* V& a. j, E- int TalkManager::countBoxLines(int idx, const Common::String &file) {
2 m2 {9 }+ R2 ]/ n+ a - _vm->_fontMan->_fontFixedWidth = 11;' y- C3 k' T2 c3 _" d+ M
- 5 l2 R9 n/ g0 W8 h) V: w
- // Build up the filename. s0 S) o. u. m4 {
- Common::String filename;
1 N& I4 z% }* }- \: c5 z; X& o% Z - Common::String dest;- V! l. @6 I1 e l
- filename = dest = file;
# h& w! T- U* }0 U8 b% r0 S# H6 Z. L - while (filename.lastChar() != '.')! B3 t) @' V- J- e
- filename.deleteLastChar();. X7 c# L q' F4 [+ w6 a
- filename += "IND";7 ~! u8 z" G3 ]4 m: Q) ^) [
- . l( j, M- Z- N$ L4 I1 K! C( x! c
- Common::File f;
# Z8 _& F5 l) g" }; l7 m, Q1 J - if (!f.open(filename))
2 _3 e* N$ [5 c/ L; p# ` - error("Could not open file - %s", filename.c_str());/ E, H/ @0 {! h7 R+ H+ K. @6 s
- int filesize = f.size();9 [+ Z5 N4 d9 F. L n+ Q0 d
- assert(filesize < 16188);
) m& F/ A3 y$ i3 | - ( k7 n9 h7 t" _9 Z! e0 v
- uint32 indexData[4047];" Y* W c8 ~- D
- for (int i = 0; i < (filesize / 4); ++i)
" u( l8 W, s# ^8 ^& _, I( C" b1 w - indexData[i] = f.readUint32LE();
0 y7 u3 p+ i: K0 R8 n - f.close();
, m; A; o0 a* o6 N - 0 x" @ H5 a) J9 R4 e
- if (!f.open(dest))# d! _2 Q c9 }# R* T
- error("Error opening file - %s", dest.c_str());- C! F# @+ ?# J6 y3 w! v. Q
- - ? j9 U3 Y2 Z# {9 Y
- f.seek(indexData[idx]);. k+ w# ~4 q3 G( v) b1 ~8 S
- byte *decryptBuf = _vm->_globals->allocMemory(2058);
8 e& y& M% n; [# a1 { - assert(decryptBuf);
( u7 z* V& T% Q8 W' X& j. T% J
4 o. d2 e, q& _4 V* I- f.read(decryptBuf, 2048);
3 p$ @* v+ U& M) L - f.close();8 d. ]1 l& Y8 d* k
0 O% J" O% k( @8 R4 m- // Decrypt buffer
( U# A4 d* x& V( O. R - byte *curDecryptPtr = decryptBuf;
1 c m9 n. m/ I o - for (int i = 0; i < 2048; i++) {
) c% _2 ^0 r5 k# k - char curByte = *curDecryptPtr;
9 k# D5 d c+ v0 Z& r - if ((byte)(curByte + 46) > 27) {
+ q0 R. \ B' q- J- b; d X - if ((byte)(curByte + 80) > 27) {& f. p3 L ]; p9 P' f2 T' W/ B
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))0 g) `+ g0 g% v( v4 h
- curByte = ' ';& V# L: r" U5 D+ p% K
- } else {
( a6 @$ X5 |7 i6 @& M/ T - curByte -= 79;
/ _, D6 |) n9 H* _9 m2 w - }
6 u( d; b$ o& w e+ _" B - } else {
( z% b! V$ p9 W ]1 e9 V l - curByte += 111;- k+ l# i% u* z% \
- }% ]3 |$ r5 m8 K) r; a! G
- *curDecryptPtr = curByte;
5 z) O6 a [' g+ j - curDecryptPtr++;
4 [4 b$ N B2 v9 O; L4 j, q - }9 y# @# o3 b( h- \$ a2 J4 S
- ; h G8 c/ E9 z4 B$ o- v. o
- // Separate strings
4 D4 i# I, `7 Z# c: ~: h$ N" d - for (int i = 0; i < 2048; i++) {& I* }/ G0 u4 i, R, t [( M
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
. `! z, X1 Y% q. H, t - decryptBuf[i] = 0;& S- w% r$ |1 A/ V3 ~. C" [
- }* k5 B3 G; p' G f
- : _ O9 o4 `. F1 Z
- //add by shane007
% @9 }# M. j$ I \ - //debug((const char *)decryptBuf);7 T, {+ y: l' r5 r: W* J
- & @4 p7 T3 R& e' t
- // Check size of each strings in order to compute box width
* u4 G3 ?+ Q% c4 [4 j7 f - int curBufIndx = 0;: f0 |% ?1 y. G8 V( q- Z5 T. o9 ^8 G
- int lineCount = 0;
8 V0 q7 F. ?' Q; L; g6 O: x - int lineSize = 0;! R v) X( f1 z2 ^
- char curChar;
( r2 u" C2 ^; k9 O$ a2 O( h - do {
7 \: {# { @6 `2 T0 Z0 ]3 K - int curLineSize = 0;
& |2 Y" P0 b9 ]/ H* E/ D% `( p8 r0 A - for (;;) {$ J! |1 b9 g! N$ L3 ^
- lineSize = curLineSize;
( S" e; n' B A! Z - do {
& h0 j& a" l6 M) v- ~3 H - curChar = decryptBuf[curBufIndx + curLineSize];* f( m! P- B2 f# u2 }- k
- ++curLineSize;$ v) n- P q# Y U
- } while (curChar != ' ' && curChar != '%');
9 S0 h1 w6 ^( a# E; Y- {4 x: V
7 }1 m& r0 S" @7 V* q- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
|3 Y$ c8 u0 ]$ [ - if (curChar == '%')0 ?6 p a! f1 U2 K& I
- curChar = ' ';* q8 j. d C0 B Z) W% K, h1 c" j; v% `
- break;2 e, d4 c( b+ O: y# |& P
- }
4 p4 m/ J H' X0 P2 ], y0 a5 o
3 w0 I# N9 x& z7 W. a0 P0 C/ ?8 V, Z- if (curChar == '%') {
V) R8 T+ {8 X9 g8 R3 O - lineSize = curLineSize;
! L# ^6 y# j+ s% n* _ - break;
- }' e# _2 t7 t1 M) o: @ - }2 @$ x# l1 a* v& @: W
- }* R! [. k4 w3 I- j
- ++lineCount;
: f& b+ z' V5 r4 d - curBufIndx += lineSize;( ?8 J7 B3 p! I+ s+ k
- } while (curChar != '%');& c3 t' |8 I. D! j) q& g) n
- _vm->_globals->freeMemory(decryptBuf);
5 L) W3 V! G& O6 T& O - return lineCount;& A3 a) B0 h0 g R3 t
- }
复制代码
7 N0 i" O/ z/ r% i" d5 M/ Y
! q n( E6 Y7 L |