本帖最后由 shane007 于 2023-8-12 09:10 编辑 0 k+ d7 r* X5 F3 C2 y1 S' k
" [$ u7 T0 K& y! b! @
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
, y6 p# M' y1 P) c4 ` 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。( o! N& X5 f$ }6 \6 Z! M, a$ E8 K
6 p$ f% O0 k' X- i) s2 E 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
+ Z* `* f q. z; w% U/ u RUEAN.IND/ n' |' L2 ]1 H. c5 q4 ]* Z
ruean.Txt
) J8 Z! A, @% E% | x, r0 a' P
1 P; ~' x; A. h *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
) v6 F# c1 z: T) r! j# S 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
5 |; m1 ]; e: u7 g7 Z
" O* p" O+ b# I2 T- u! M$ m2 w1 v& j7 n: a+ k) z7 A
*.TXT的解密代码如下
% d1 g& Z* K; |. |- int TalkManager::countBoxLines(int idx, const Common::String &file) {2 d$ r" D9 |& U ]
- _vm->_fontMan->_fontFixedWidth = 11;% m: l" d" d- Y/ [- ~* O
9 p4 |4 k7 L( H4 f' m- // Build up the filename
; B# D2 @% K. ^/ H6 J - Common::String filename;! V5 D: s% D) R* K" h
- Common::String dest;
( b% j* p9 a3 K- H# x5 f& M - filename = dest = file;
/ }2 H1 V- K: c F& R7 k$ w2 x% B - while (filename.lastChar() != '.')& W- i% X, C7 Z; i7 ?3 g
- filename.deleteLastChar();
5 q& X. I+ E) F8 U, ~ - filename += "IND";# z& F7 N% `% Q$ u) P4 Q
6 j4 x/ C0 K9 Q6 u2 N" A; M- Common::File f;' n9 H( ^/ o! r; ?3 }* d
- if (!f.open(filename)), c: v9 ]7 @6 ]5 @) g& x* z) |
- error("Could not open file - %s", filename.c_str());
1 F6 J2 }2 S$ ]% q. z9 N - int filesize = f.size();
! q* I; e* C9 C8 [, u - assert(filesize < 16188);6 Q* y6 |: H! K2 H+ Q- \
" o3 c5 X, e% W4 G& v7 V- uint32 indexData[4047];
# b9 ~* \5 I% T- ~ - for (int i = 0; i < (filesize / 4); ++i)
% X/ B/ l5 ~0 e O3 J' c - indexData[i] = f.readUint32LE();3 r. K8 W! C3 Z$ j# _
- f.close();
3 C2 X% D0 U9 [' D% G$ G$ j* K5 v - ' ^7 \1 X( V6 z( m; C2 {2 y0 w
- if (!f.open(dest))7 z( Y# M6 Y+ ~* U& c$ T! A
- error("Error opening file - %s", dest.c_str());
3 _, e& F& x% \" L$ P
! B: m* L$ y% }( t- f.seek(indexData[idx]);
/ i" z' y1 N5 Z# J, M, S- s& {" l: G - byte *decryptBuf = _vm->_globals->allocMemory(2058);# G j% q P4 R& ~7 m4 C- x4 c
- assert(decryptBuf);4 c$ A) d) Z0 ~' F
" ^, b3 ? n0 F3 R! f) N- f.read(decryptBuf, 2048);9 w. a% c/ l6 K1 o9 [; A$ V
- f.close();
9 D. O J) b& _; \5 T- d, E - , U3 y$ b3 E* q2 v
- // Decrypt buffer
" }5 x( E! \3 y& ~6 ]% V2 w - byte *curDecryptPtr = decryptBuf;
7 H8 G8 v5 {* k( e- y- ^" n/ g( Q - for (int i = 0; i < 2048; i++) {4 u. M. [% B6 J Z1 z+ `: A
- char curByte = *curDecryptPtr;( O B3 B. m) J
- if ((byte)(curByte + 46) > 27) {3 ^5 o& r/ b. N0 y
- if ((byte)(curByte + 80) > 27) {
$ h( O! N4 Z4 g5 Y; I% p/ `2 ?6 ~' V - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
. [) f+ B! H: D- A! W - curByte = ' ';
! z i/ D2 s: ^ - } else {
5 m( F& }7 }" @9 H. O+ }4 A1 d - curByte -= 79;
6 r0 `" m. }0 D3 ?3 _9 X: U - }8 \8 U! U/ i6 e4 c; T! E
- } else {! z. C" A2 B( B$ I- T/ ?( I0 ^
- curByte += 111;3 @+ q5 n4 m. |; n/ n
- }1 B2 r2 s% n+ V! ]
- *curDecryptPtr = curByte;
) _9 K) Y( U; d5 s. ~ - curDecryptPtr++;
! k$ N- E; E0 x - }8 T s% l% Q8 S$ i
0 c) x1 L0 \0 P- // Separate strings
4 x. p) Z! O- A8 z) O( P" [ - for (int i = 0; i < 2048; i++) {/ R8 T3 h t" f# P7 N' u+ u
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
S' R! \9 a0 i" r - decryptBuf[i] = 0;
" g: M, E; t' L - }
: ~6 A' j) h J Q - ) n* j# p% S* F3 J- ^
- //add by shane007, I8 w9 p ]4 Z9 s6 K1 F& Y
- //debug((const char *)decryptBuf);# w" K/ T8 S/ S2 N- V2 K! ?$ _* T/ u
- ( {: V; a9 U: G- ^
- // Check size of each strings in order to compute box width
$ L4 J% v0 r4 T - int curBufIndx = 0;
* n2 g* k3 m, S/ E5 z3 V4 V - int lineCount = 0;6 W, `- k4 d# K
- int lineSize = 0;
, } ~; V2 c( ^ j$ k" c - char curChar;
% C" G$ P% m) M - do {
7 ~: m* H% l" M- J' i' G& r$ Y5 V3 L - int curLineSize = 0;
4 E) \5 P) p' ]! {3 B! Y - for (;;) {3 u* M/ F' Z4 }3 ]( s
- lineSize = curLineSize;
% L7 E$ E/ G9 @" Q! Z - do {1 \/ R; O1 T* a+ h5 S
- curChar = decryptBuf[curBufIndx + curLineSize];+ G) l# u7 a$ p% a, u$ u
- ++curLineSize;* b, h: H& N; |
- } while (curChar != ' ' && curChar != '%');
; ^( S% e; L% _- ~' v - 6 T9 p' ~) f5 V
- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {3 a! Q" q% L; b' Y
- if (curChar == '%')
3 L! a2 i" z$ \: Z- U6 a - curChar = ' ';* J' R/ w/ ~$ B7 U
- break;
& `7 a* }. _* a s1 n - }. o% d. O9 G9 D7 L) D# V& n I$ M8 X3 {
2 i. G: y' ~6 b) U- if (curChar == '%') {: B5 k. U% M* W' d* Y
- lineSize = curLineSize;
. q* e. i& h+ W! o$ \; G' o - break;
7 ^4 `2 \8 `% |% x8 F0 \5 a1 G - }
3 B$ a2 E# I% r# n - }
" a4 ]6 c @2 b5 z9 _ - ++lineCount;& a3 f7 r+ a1 c$ S
- curBufIndx += lineSize;! M) n- h2 {5 z7 Y: e
- } while (curChar != '%');" M5 p- C; D, ?/ v
- _vm->_globals->freeMemory(decryptBuf);
" w- b+ U5 ?1 D5 _ - return lineCount;( a) i+ I5 w3 {+ ^/ m3 w$ g
- }
复制代码 5 H: n. q( N/ t1 Z& ]
' C" J+ V3 I q" x s, h" T |