本帖最后由 shane007 于 2023-8-12 09:10 编辑 8 w9 C- Y* [1 M& K* b6 B( x1 {
# n! \9 s, j* x e
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。) R( i7 I1 G% Y+ M v0 D0 J( p" X
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
. J8 Y3 ~1 e& F3 c7 Y5 W: K+ f- R/ b% ]( @. x+ S
比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
( {; N) y2 Y% W# r# U' v RUEAN.IND# B8 h+ x8 d) n( [2 R
ruean.Txt" N9 a0 }9 w3 X0 J3 h
$ D+ t# T" ?5 r' Z: ` *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。" g. x' Y) n: p
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。' p' z/ G% d( {. x! }
* N L) Z3 w/ U4 A U9 _: g4 J+ Q* O0 w w8 a5 _6 B! }( T
*.TXT的解密代码如下" n7 Z% }' j- h; P, N+ c6 C
- int TalkManager::countBoxLines(int idx, const Common::String &file) {6 b, u, E1 T y2 ^$ c
- _vm->_fontMan->_fontFixedWidth = 11;7 f7 z% m% U# v* |
- % O) B+ j: e F
- // Build up the filename
- g. }" x* j; j5 C$ q3 k - Common::String filename;' a! A$ K y( z; i" s! i# c: y
- Common::String dest;
$ G7 a A4 }- V: L - filename = dest = file;7 F+ n; A+ b5 j0 I4 e
- while (filename.lastChar() != '.')
" c; H( V& z9 }' h" e - filename.deleteLastChar();
8 ]. A) X6 A$ A, R6 p" m - filename += "IND";% F4 | s4 D" H+ D% \6 e. A$ E# w8 ~8 D" x
- * d" b+ Z4 n0 Y+ o$ ?
- Common::File f;
5 @- Z4 m3 Q2 } o" [" q( u - if (!f.open(filename))0 S) u; f$ R* p3 X$ d$ ?- L
- error("Could not open file - %s", filename.c_str());
9 I6 y2 E- \. B7 l. ? - int filesize = f.size();+ }8 N ~5 E8 q* M
- assert(filesize < 16188);$ d. v5 \. s2 C* l f
- / g+ w" j/ m& ^! R! u, S
- uint32 indexData[4047];* X0 [( m9 `' ^! V
- for (int i = 0; i < (filesize / 4); ++i)
" }" A: G* c5 l9 g9 V+ Z* O4 E" _3 {# l - indexData[i] = f.readUint32LE();1 E6 H; g* q8 k7 X7 R
- f.close();
& @ |) p, `$ t
) B* ^+ C" z$ c# y0 ]$ b: F3 t- if (!f.open(dest))7 ]1 A! [& G. o% @+ [1 Y
- error("Error opening file - %s", dest.c_str());( l$ m& {$ E0 Q" D
- * k* T( @5 A# q A* f; [
- f.seek(indexData[idx]);1 {$ l' n, n4 \. v+ ]
- byte *decryptBuf = _vm->_globals->allocMemory(2058);
9 W5 Q8 {% A) \: s - assert(decryptBuf);% @( u5 a# j }+ M
5 p& n$ j! M; R9 y5 c/ _8 n- f.read(decryptBuf, 2048);
( x3 ?4 g* u0 f$ a - f.close();0 ?0 z3 V4 n3 ]3 W/ H
- 5 v" K' ~) B5 U
- // Decrypt buffer2 {7 L2 X8 h- k' t
- byte *curDecryptPtr = decryptBuf;
: }' K" W8 v/ w* J8 Z. N) \& n - for (int i = 0; i < 2048; i++) {
, X2 L( L9 G: q0 k% n - char curByte = *curDecryptPtr;
3 h# ?; V* f/ T5 | - if ((byte)(curByte + 46) > 27) {( ^" J, E: Q; H4 J$ z& H0 G! e
- if ((byte)(curByte + 80) > 27) {
" B* g' Q z; M' A: N - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))1 O# S( M% Y1 Z$ N; O7 C; b% v
- curByte = ' ';
! Q3 k* \( z# k - } else {
6 S- O' p1 l3 S$ k3 `9 H - curByte -= 79;
$ w/ a( V$ B# |1 m3 ^2 I" j% Y - }
7 Y4 @: z/ k& Q' \/ Q$ O - } else {+ f$ j+ o. |2 C( M' K2 t
- curByte += 111; ~+ m2 U0 d: Z# A) [8 b, k
- }
. w4 [. p4 t. d7 R3 [/ j - *curDecryptPtr = curByte;
# e! N2 C6 O; J* p; t8 U - curDecryptPtr++;
2 s t2 l, ]& k - }
7 C$ a! f5 l6 a4 E! o
+ f% m* O, R6 P& C3 V) l& n- // Separate strings" Y+ d0 Y6 c, I9 U, I( Y3 k0 [
- for (int i = 0; i < 2048; i++) {
* g$ G& F; y: ]% g6 h! q - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
/ Y% d; x( d& f5 j% p. F - decryptBuf[i] = 0;
: {. N& U0 h1 s* |5 y - }: z3 [9 g/ z% u! D) c
- 1 v/ h7 Z0 Z/ M
- //add by shane007
/ a9 }5 e9 g% _, f* D - //debug((const char *)decryptBuf);
: ^9 U1 u4 ^5 S& B3 X, _1 T - ; J: d) v' ^: h" ?' f% D, p
- // Check size of each strings in order to compute box width9 @" L. I; w. F M
- int curBufIndx = 0;
" X( I9 ^& c0 S4 I8 `5 \0 t - int lineCount = 0;
: D1 N# r6 t8 o% u& o - int lineSize = 0;
: ^0 R) A5 ]# G- ~. @0 C4 }( e% H" \ - char curChar;) L3 x- C+ ^, k1 i
- do {
8 f, o5 H& y r, ^$ v% a - int curLineSize = 0;; L2 `/ x/ M! E$ y+ {
- for (;;) {) C5 m, F) t. S4 z$ h" V
- lineSize = curLineSize;/ V3 z; i2 [" {9 d% N
- do {0 i2 c* S+ C# O4 L' i
- curChar = decryptBuf[curBufIndx + curLineSize];6 _2 p) q$ n, t% f5 v$ m8 y
- ++curLineSize;
" C* f. V# c- ^; E ~: G - } while (curChar != ' ' && curChar != '%');. g. {* |: k4 s8 x. A" S$ n( |
) b0 `6 C _- l- G4 Y C- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
% z/ q% ~& S& @3 Y. a- }8 Q - if (curChar == '%')
8 B5 m& ]9 Y! c9 ], r1 _, m - curChar = ' ';
# G% r: A! J7 @. o( k; _ - break;7 U5 W/ ~$ I! i" K/ y
- }
4 ?: I/ X8 H2 K1 e6 o7 X4 p - 0 X: P, q4 P, Z5 n+ T; q7 r! d
- if (curChar == '%') {
$ S) L6 O4 q" e2 V* s+ Q# z C, V/ B4 W - lineSize = curLineSize;" x* e4 ~: G2 E" ?
- break;
$ a i7 g. t) D' c* J - }
/ \- D9 ~" S9 Z9 X' o( C - }( _/ _& y& @& E4 l
- ++lineCount;
' F# ^1 K6 m: T9 R. m+ t" B" N9 z - curBufIndx += lineSize;9 l" v% s( d6 o% H7 ~1 r
- } while (curChar != '%');/ N* T$ _) P8 ]' v3 B$ v
- _vm->_globals->freeMemory(decryptBuf);. T5 u: h2 Y9 q# ~" q
- return lineCount;
& |: c3 {/ Q" P2 r - }
复制代码 $ d% G4 x% D$ D* D0 h( b0 S1 D
9 w( N- \5 z5 z* L! N
|