本帖最后由 shane007 于 2023-8-12 09:10 编辑 3 s! _$ |1 o! D3 u# k' B
+ j" A9 Y' c6 j7 y/ i/ M& s9 R
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。3 r5 x3 T/ ]! ]* K% Q; u
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。: S, M8 Q( q) e# ~# ]$ ^/ l N
, d/ M% r2 k w( H: o" x+ q
比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。! _+ V, S% ^6 F1 u7 E- e
RUEAN.IND
6 O# M2 Y, g; _# Q* c ruean.Txt+ H6 r( `; V. S t; m9 ^1 k
! Y. u: F: V# o ~6 j7 ?
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。7 g/ o$ i2 W$ ]! A5 s' ~
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。( ~1 `2 S0 }3 x
& [* x4 i6 ^9 }4 B. |% u1 N/ `% z$ z+ J2 @
*.TXT的解密代码如下/ x/ v( X" {# G2 {' U
- int TalkManager::countBoxLines(int idx, const Common::String &file) {
( ?6 w, b9 C4 B6 {& G; r - _vm->_fontMan->_fontFixedWidth = 11;' N) q! V+ G- }1 [+ E( u& N
- ! H+ h3 c$ C& b( h; e0 _
- // Build up the filename
. y6 l8 j0 H# ~ - Common::String filename;( l; s7 x! Z1 U- T1 G _
- Common::String dest;
8 \" Y' \) w& g - filename = dest = file;
+ X0 D- r$ N7 `4 n. F - while (filename.lastChar() != '.')6 b `$ u; T. p( E) I
- filename.deleteLastChar();3 p3 M, Z' s% N
- filename += "IND";7 c1 t* t0 w& Z3 s/ c' c4 a. e
- ' [7 v% b) H7 k( }/ G
- Common::File f;
C V# R8 s% F" @ - if (!f.open(filename))
) b; d- R3 [2 W* X - error("Could not open file - %s", filename.c_str());
& L' \$ v6 n/ x. g5 B ^9 G- { - int filesize = f.size();, ~- r- g# f+ ]/ Q; x
- assert(filesize < 16188);
( e2 E9 z- V" R2 C; a) J/ i - ! s9 L8 f V, p% j9 S+ o
- uint32 indexData[4047];5 Z7 {: K5 g( b2 w1 f, q$ i
- for (int i = 0; i < (filesize / 4); ++i)
* B+ ?- B1 R; M - indexData[i] = f.readUint32LE();
% ^+ e e" w e* ^4 V - f.close();; H# F' E% j% r [0 f
- / G& a; N, T9 C1 h3 R
- if (!f.open(dest))% N2 o$ C9 y r
- error("Error opening file - %s", dest.c_str());1 o, T; I1 Q' r: P, _! M2 G' w
5 v5 V4 Y* ?5 @, f: t- f.seek(indexData[idx]);
) q/ U7 x- c& @) e5 i; m- z - byte *decryptBuf = _vm->_globals->allocMemory(2058);3 }3 c, ~- k+ S
- assert(decryptBuf);. A/ {$ M- i& m9 i# O7 j
1 w' Z4 u5 i( C) a- f.read(decryptBuf, 2048);) E$ A: v' J9 s2 R
- f.close();* o( c: g! C; g( R. g
- - E: `8 D; \8 H
- // Decrypt buffer/ c3 Y4 _9 Y \. @. I6 z5 K
- byte *curDecryptPtr = decryptBuf;) n @" k# F p+ `
- for (int i = 0; i < 2048; i++) {- j$ h- E; M# M. V) V2 h& B3 |3 x. z [
- char curByte = *curDecryptPtr;
+ m& Q [; N7 r5 e - if ((byte)(curByte + 46) > 27) {7 F# T6 r2 T4 R7 |1 \& K \8 c# a
- if ((byte)(curByte + 80) > 27) {
( K8 a; }- i5 Z5 e% o; T/ z - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
$ p$ O+ j% D2 _( O - curByte = ' ';
* b, B }2 F7 W' e6 w+ ^ - } else {
" A& P# Z, o, G- a. ?& O3 ] - curByte -= 79;+ S5 N! [1 D {% Q
- }, g4 u l1 H: V
- } else {5 D' t) Z5 R. c, ]' [: c5 R
- curByte += 111;8 d( y1 o& I# p, v
- }
3 R2 y/ }1 t9 Y: X - *curDecryptPtr = curByte;+ I- i8 |7 \1 O* Z9 _: V
- curDecryptPtr++;
7 f) {2 p M3 Q% @4 P' m - }
0 i* c1 c$ L. P' U1 W$ z - . F i: p- w1 q7 P- Q. Q f1 m
- // Separate strings9 L! \1 C$ E2 O# K" j
- for (int i = 0; i < 2048; i++) {
. X6 e4 o; [6 [2 z - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
6 V3 _2 ]2 q8 a- c - decryptBuf[i] = 0;
4 e% n( h( U# n- V' R- _ - }& ^1 @" P X! p2 q& X3 Q) T
: G- Q: j2 y" ]: v, d+ j a- //add by shane007
- \+ e$ T* e( [' D5 R# e - //debug((const char *)decryptBuf);
8 d+ m& e9 c8 n( h4 A - / F2 P: u' @* T
- // Check size of each strings in order to compute box width
- ~. T8 b0 Y6 z ]" b - int curBufIndx = 0;7 D; j1 a% S8 Y0 `
- int lineCount = 0;
2 N5 s. Q7 l( f4 p# R1 n, p# D1 i4 c - int lineSize = 0;1 x: O$ j- Z; s" b( g
- char curChar;
?1 K% O) ~8 C0 b" m; z6 ?6 O' L - do {# S* m' ]5 |: x
- int curLineSize = 0;
7 q/ T: Z A9 n/ {% y( i8 r# e - for (;;) {
" a! d* l: \4 P; {- K - lineSize = curLineSize;
3 Q/ T! U* c7 m% C- m - do {. U( I/ O3 Y" b6 S0 g
- curChar = decryptBuf[curBufIndx + curLineSize];5 F4 k& D* m# x4 F4 ?. |1 ~
- ++curLineSize;
$ l" t$ S+ m2 Z @3 L" H - } while (curChar != ' ' && curChar != '%');
& J F! Q* |. s1 q! J( t
1 y9 V4 e' ?9 h% P( ^- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {* d4 X6 H* r* i8 l D; a2 N2 f
- if (curChar == '%')/ t C5 T& w- q2 j0 r3 J
- curChar = ' ';+ o Q! \- R5 w- ^
- break;8 r7 M7 t9 M3 @
- }
9 ^ p- t2 Y; D0 w - ( f2 X8 D5 @6 b+ m" b! r1 _
- if (curChar == '%') {
; E$ o2 Y x5 Y, f* ~7 R - lineSize = curLineSize;
& u) f$ p9 n2 o - break;
* ^3 S* a0 |( M2 ^ - }
, J Y9 q, P! Z/ e5 w5 } k - }
! C; z8 }1 z: c; r9 G2 S - ++lineCount;: F, i/ k: G1 G/ d. @$ G! b
- curBufIndx += lineSize;
4 O+ f- E9 [* x - } while (curChar != '%');
, I/ A S$ i" Z6 T- S4 ~ - _vm->_globals->freeMemory(decryptBuf);
- ]) o5 u8 I9 Z$ O( n; n. P. M - return lineCount;
) ], E7 [; {" m( A' a1 J6 @- E - }
复制代码 + d0 l; k+ c" _; l2 O8 b
7 y, j" P! P+ F. d( e7 @& B |