本帖最后由 shane007 于 2023-8-12 09:10 编辑
8 N% G- W% D h( R: z3 l2 C
+ _6 v, X9 ]1 p: d# x( k1 y6 c 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。' B" ?6 [' x' i" j2 v
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
8 J4 b& \$ n/ B" v* i, Q, b
* i6 J6 J" g1 H% V r$ @ K+ m1 x 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。9 _# G) p3 V b3 E$ k
RUEAN.IND+ j: R7 B$ m; A6 \4 o
ruean.Txt
. B1 l! m' a, n8 p' k1 O
, u+ d+ V' M5 n. @8 S- T1 \ *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
0 d) k9 ^+ T9 j7 }4 { 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。8 x! G2 W9 x$ l9 K7 f5 L }
" X/ A$ ]) v1 ^: m$ ]# n
% r. M* S/ j7 A8 t4 P6 D *.TXT的解密代码如下
/ _+ Q! w- |+ U1 T: v' Z- int TalkManager::countBoxLines(int idx, const Common::String &file) {. q' L3 y9 O: ~8 H1 i% P# f H
- _vm->_fontMan->_fontFixedWidth = 11;* b2 K; j' x# L% B
- 6 y! K2 K9 R3 g0 K5 I0 Z
- // Build up the filename
/ u- f7 w8 o, H' `- a5 \) ^ - Common::String filename;
( B# U- ]" K# ]# e1 d: C - Common::String dest;- A; P" l, @) a
- filename = dest = file;
& M$ k/ H& C# [5 l" X F, A9 } - while (filename.lastChar() != '.')# q7 f2 t! W, }( f4 X1 w
- filename.deleteLastChar();
^# J$ G; z- {) X( N! w V - filename += "IND";8 J% B O% e/ k0 n F- J3 m( y
- X" i* q' C: R. i( {9 J; y3 R- Common::File f;/ I. F8 K( D4 C. e8 R3 o
- if (!f.open(filename))
4 Z O% |" ?9 P+ O, x n - error("Could not open file - %s", filename.c_str());
) T) J# y/ L0 _ - int filesize = f.size();
& D7 ]! k. N, Q# k - assert(filesize < 16188);
2 P( l* D" Q/ c5 X9 o6 q& U
9 K" d' i3 |) s9 T8 P0 ?# s- uint32 indexData[4047];
* u& D' I8 N- e - for (int i = 0; i < (filesize / 4); ++i)
3 K2 T7 W% E U0 Z$ w( T - indexData[i] = f.readUint32LE();) b( E9 G% f) ]$ S
- f.close();6 }3 B9 B6 F/ e4 L
- , L0 M( t% P V" x4 d# g
- if (!f.open(dest))
1 Z R- H& Z- g3 f. ? - error("Error opening file - %s", dest.c_str());
6 h+ l8 O9 R( J - ! B6 x! T, l$ M) q+ P# k( \/ N
- f.seek(indexData[idx]);& A# ~0 z* S3 W+ |; p; H" @0 Y
- byte *decryptBuf = _vm->_globals->allocMemory(2058);& l x. i9 R2 C
- assert(decryptBuf);6 C( ]9 c6 z, C4 U8 V* p- y! d
- 1 B5 H6 o/ |+ a" h: d) x6 N
- f.read(decryptBuf, 2048);
, `" q. f. I$ Q& w* \- p( Z - f.close();& z3 J5 x, ?, w" _
- # H/ }" s2 q2 Y, z6 G
- // Decrypt buffer
' X, |0 s! H% A% p( g$ t4 D - byte *curDecryptPtr = decryptBuf;6 {3 Z. q& j+ K7 R
- for (int i = 0; i < 2048; i++) {
, e. F! S" E) v - char curByte = *curDecryptPtr;
* K) b) s2 |$ b; p. P1 U1 d - if ((byte)(curByte + 46) > 27) {. [( z+ A" B4 I
- if ((byte)(curByte + 80) > 27) {
+ K8 s# F# R% z& d. Y, f - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
* h( G! z) b" \0 |2 i0 j1 l! `" r+ Q - curByte = ' ';
6 \9 L7 c9 Q! ~. e9 d - } else {2 L1 ~& d% C9 ~# C( w; Y7 E% b
- curByte -= 79;
; N9 a3 n, }, u5 x# V. J - }; i2 o3 l$ i' V) x
- } else {
! `: ~( R1 n; b - curByte += 111;" o: ?4 I1 B) ^0 n8 |
- }
( G0 d2 K; ?- U! D1 {% u - *curDecryptPtr = curByte;
5 }2 g$ k( S% X/ [ - curDecryptPtr++;
7 C8 w) o1 K: y" y1 ~& v9 w; B - }
! ~! S3 Y f) p9 \3 O! h: @ - $ h- u g7 Y# E0 `
- // Separate strings
/ Z4 p( w( `+ Q4 z - for (int i = 0; i < 2048; i++) {3 [1 e l$ S, m% z0 ?( d
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
& D$ F4 U. V9 c: q" e. x* ? - decryptBuf[i] = 0;
) k1 e* w X( b8 F4 U4 w* _ - }
/ F; \! J1 P$ i - M5 @5 O- P5 j: @0 c
- //add by shane007
. H. A! q; V ?4 G& h2 {9 E9 ^ - //debug((const char *)decryptBuf);3 s0 X' E5 J3 G" p
- $ H1 t, ~: H( T3 O7 u
- // Check size of each strings in order to compute box width6 W+ m! H4 \0 U; t: C
- int curBufIndx = 0;
; B8 Q* Q4 e; G4 U, j* a - int lineCount = 0;6 l1 {5 b0 S( e- G6 o
- int lineSize = 0;
& J) q4 _& U( k, R. ` - char curChar;
0 ~4 O" H6 }- F- O1 `9 N2 F. V& D6 R - do {4 ] S9 m/ p& n4 W% x" Q7 Y0 `
- int curLineSize = 0;
+ y; F7 }2 a2 w$ ?% o! }7 ` - for (;;) {
( |/ R: p j& k* U3 m - lineSize = curLineSize;
L! |. C' a/ W9 s - do {
0 ] D1 S0 r: ?3 m6 k - curChar = decryptBuf[curBufIndx + curLineSize];
" q$ f6 `; ]# w( i5 b1 E V5 K0 p - ++curLineSize;) }2 ~8 E& I9 S6 b6 q* p% ?1 w$ I
- } while (curChar != ' ' && curChar != '%');! x6 R5 W$ M2 [' r$ Q, u; b2 K3 X# Q
+ N3 S3 A w0 q- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {$ f; N! S! ]* e. y- q8 p
- if (curChar == '%')0 S" t8 h/ `/ J3 z3 j/ U, c2 R
- curChar = ' ';
5 e, B' R7 m1 N - break;
# S3 O5 a' H2 K# r# w. A5 f5 R - }
% b% u3 r4 |9 p$ }) T
% E7 Q5 `# V2 w+ B2 m7 r- if (curChar == '%') {
! R5 e' M( V+ V9 N8 G - lineSize = curLineSize;- y) C' ?( Y5 C* W |0 b
- break;+ d) \4 G' p0 y( C
- }" J# H! N, {1 t8 `
- }
g- F3 [0 s' {: |0 h5 m( v - ++lineCount;
, V2 |) D2 f# V - curBufIndx += lineSize;1 h0 d9 y0 V& z
- } while (curChar != '%');+ w1 d; x( ~+ ~" g. E- {
- _vm->_globals->freeMemory(decryptBuf);* ?9 {" J$ I+ X# A, ]+ Q
- return lineCount;, p5 K% I. M+ ^# Y
- }
复制代码
+ O! f% R: h2 B$ T1 p6 E x
9 d" v1 C/ a7 z. G& C" @" L$ |" R' S |