本帖最后由 shane007 于 2023-8-12 09:10 编辑 $ \# z" V" I( U, k
) U4 s7 |0 _( m4 C2 U 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。% T7 u3 m M5 E/ C" @
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。 J" l& E, k5 w/ x
) r9 ?# M, I; f4 ~! x- F 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
) K! f9 r K& L' [: F, o$ t RUEAN.IND: b( g4 n: H' _' `8 s# I8 d+ B
ruean.Txt5 F* C: h/ B& x
2 y/ F* K& a3 O0 O0 Y2 G' L *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
3 B+ H. a0 G& B6 _4 _( W- Z/ c 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
9 k' @6 | M7 n8 v
?5 F" c' n% G" x
/ H4 X$ o! b! B k1 O- g *.TXT的解密代码如下- {( n: ]9 @5 z$ I2 V
- int TalkManager::countBoxLines(int idx, const Common::String &file) {8 J" u" m# H3 }5 ~) b/ B
- _vm->_fontMan->_fontFixedWidth = 11;- u( X9 J: U3 }7 {! [$ n1 W
) I6 v- P$ g! d% m3 W- // Build up the filename
) B* ]- e/ p- V; S& |2 ^3 ` - Common::String filename;
4 c3 D: K- k) E7 ~ - Common::String dest;
' j$ J3 C0 |& A* O - filename = dest = file;: ?. t: A( z, R% N: u% X
- while (filename.lastChar() != '.')5 F" z8 v; `6 Z2 S
- filename.deleteLastChar();0 }0 q: g& D( |. r6 N- ]0 B
- filename += "IND";
4 N4 O$ ?. O/ W, d# `4 {7 n8 G - 0 ^8 h* k5 l5 @" g
- Common::File f;
9 X+ E! o+ g: D k! A4 H: j# u - if (!f.open(filename))
5 d6 O. K8 A/ \# W6 s" l( I - error("Could not open file - %s", filename.c_str());: _. }. X g$ x0 E& |( C
- int filesize = f.size(); j! b+ z8 D# H" m' ~
- assert(filesize < 16188);6 u G! ?1 Y# f
; R% d$ U' s- O- uint32 indexData[4047];8 x6 m Q$ \& a3 _7 q7 P
- for (int i = 0; i < (filesize / 4); ++i)! `( V' g* k' c0 ?
- indexData[i] = f.readUint32LE();0 p0 f* w3 o5 X5 |
- f.close();+ a" s! e* {( n8 j8 j/ M9 h) R
: T: l% z9 e! f7 _. e1 i. C- if (!f.open(dest))$ T6 H, n# ~# E/ x; d
- error("Error opening file - %s", dest.c_str());
3 b' y1 z( S5 A0 a: `( n3 d& { - 8 T1 {; m4 r: Y% u, {
- f.seek(indexData[idx]);8 p1 ^+ s# D# K, z4 d7 O
- byte *decryptBuf = _vm->_globals->allocMemory(2058);
1 P: m4 f% ^/ O) z( v - assert(decryptBuf);
. V# M1 s! Y( |6 l4 `. y9 G% @) h
8 }1 Q+ u7 ~- l; e! u: d- f.read(decryptBuf, 2048);
( b% U9 U0 c8 g4 V. e1 o! Q: {8 I6 t - f.close();
|4 E( O' p; j8 n5 l5 X6 Z - * G& Y; M1 s: y+ m' d. u" [( d
- // Decrypt buffer. ?* t- I+ `8 q; |8 U
- byte *curDecryptPtr = decryptBuf;
5 M7 U/ S {9 e7 _5 h - for (int i = 0; i < 2048; i++) {5 u6 l4 k3 H) v2 x$ v& O
- char curByte = *curDecryptPtr;
$ {: J9 Q/ u: G" X- @" K! E - if ((byte)(curByte + 46) > 27) {; a9 H7 s4 i2 \0 F: T, j& ~
- if ((byte)(curByte + 80) > 27) {0 P/ g' t6 M; T$ w% v8 s; ^
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
4 q1 D- F6 }2 c" G - curByte = ' ';# k' w3 x0 w/ v3 e: z
- } else {
% s0 }+ H& x* _# Y. E" R2 C) I, k - curByte -= 79;
5 L) C7 F" C$ f7 x' { f! v - }
* z% c9 i: r+ E - } else {
! A, K' \7 v( D# t2 i! V9 [& @ - curByte += 111;; I+ o2 [' Y2 [! f9 K6 G
- }$ x7 R0 O. _7 m! K M5 R. [
- *curDecryptPtr = curByte;
. ~+ {: _$ B$ G7 i1 | - curDecryptPtr++;
- @+ P1 D6 i8 G& T( n - }
) @# ? |! |# Y! C& d2 ^
0 |" L( S* K* q2 n0 f. ^' C- // Separate strings- n9 d$ A7 q/ B* ~) W
- for (int i = 0; i < 2048; i++) {
/ g1 J7 G# l" l4 U) L - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
$ {' R6 d) n7 ^. y* v- ^& `0 t: h; U - decryptBuf[i] = 0;
4 ?% z6 n3 p9 ^ x; ?6 u. R - }
* e% z+ R; e0 b; m: f - * N' `8 E6 m: L7 q, C: _ n
- //add by shane007
8 t4 J" T5 }6 \ - //debug((const char *)decryptBuf);3 I8 J H: n0 h2 F4 }- L
- . `8 Y5 {; Q; \$ W
- // Check size of each strings in order to compute box width
6 h- V- S- s6 A4 k2 S5 W( r - int curBufIndx = 0;
u$ }' z/ h' W% a! k' r3 `7 @ - int lineCount = 0;# r, c! T1 ?! k6 W: H; s) {
- int lineSize = 0;' I. ^: s" x9 W- H% g, B
- char curChar;
T* u J1 Z7 @* y. e& O - do {9 a& g# H3 x0 i" [: }
- int curLineSize = 0;7 w3 _( E& g' }5 U. i! u
- for (;;) {
) H# _0 F% C% C% D% q - lineSize = curLineSize;; I! D6 T0 L* G$ f0 W3 J2 k0 H
- do {
' O7 `1 x; M" y/ M6 E4 r ^ - curChar = decryptBuf[curBufIndx + curLineSize];# H7 S5 H5 h' D; ?% v
- ++curLineSize;, G; [4 d% c r4 _+ N% s
- } while (curChar != ' ' && curChar != '%');, Z# X3 u% S' W( R. t" [9 w9 Y0 P
) z7 g1 l0 _. |7 o9 y+ Z- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
1 t) L, j$ ?" @) P. V - if (curChar == '%')
# ^) Y4 D: B9 a - curChar = ' ';
4 i2 u7 |+ e% W; @, H' d5 H0 \3 g - break;- o9 k; ~' V) l: \- |- l) s/ g- f
- }3 ~) w3 o" x4 _
5 p9 [$ A1 Y3 y/ E4 y! O8 Z- if (curChar == '%') {/ m+ Y n9 z! L) r0 r" k, S) @
- lineSize = curLineSize;8 P) G2 f( N0 b8 f9 r7 F: m
- break;; F' q4 S% [' S( e! e: i5 a- o+ j8 ?: Y
- }
) Z. n! h7 ~; B - }
! W( r# [! g" p" v5 r+ _+ U - ++lineCount;
+ N$ H6 R) t" k. H6 F: y - curBufIndx += lineSize;
: C0 s; Q# N$ j6 n) [+ \ - } while (curChar != '%');: H6 G; ]2 ?" ^7 E4 T6 }
- _vm->_globals->freeMemory(decryptBuf);+ I/ U. G: \+ h! P2 J* U
- return lineCount;
m8 E1 N( P& D/ F$ i5 x - }
复制代码
. E( T4 v# s! Z% e5 L, X. h* `* J- r8 P j) m! `# _: v# V( o
|