本帖最后由 shane007 于 2023-8-12 09:10 编辑 6 P4 M1 H7 j( q% e7 G c* R& P5 n
6 {" m; p. d* ^; f0 B
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
: H' {7 s/ I$ y; k- d, f4 F5 B 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。7 N3 G$ ^' g" Y. n. L& @9 @. a) U- S" L
8 H5 c: e m# Q) g3 S6 n
比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
$ ]6 n5 K5 W& ^2 q6 O0 f( a RUEAN.IND
5 [& W6 U- ~& W# j, D) t, h ruean.Txt( O8 x* [' H, }
/ K6 P3 D8 a. M1 X
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。 Z5 ~3 C9 V, l/ U
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
. L' [0 q9 m% D# g6 B! N" |6 e8 t+ S& i0 `
5 g x! i3 u2 m4 W/ }! t; n *.TXT的解密代码如下
1 u$ W: f4 X5 r. B0 r- int TalkManager::countBoxLines(int idx, const Common::String &file) {
" T' P5 n; B$ O- H4 L* Q R - _vm->_fontMan->_fontFixedWidth = 11;
& W- P7 g% J! a& q - # u# W6 w* c$ c0 s/ w
- // Build up the filename
' d) m/ B u+ C" y - Common::String filename;
4 ^! |( r' D" t' m. e. {0 g* ]% M - Common::String dest;* d6 ?8 ]1 J6 J- n; W2 e
- filename = dest = file;; q6 ?% Z, g* y& ~
- while (filename.lastChar() != '.')4 `- l" Q5 \* K9 ]7 Y& \1 ?
- filename.deleteLastChar();: i! j' b0 _, u' p
- filename += "IND";
8 E2 ?- N2 _, I u
& M: u+ e* o% v2 K2 [- Common::File f;
" v+ r6 ?* Z& S1 C, w9 w+ Q; K4 T - if (!f.open(filename))
. y- e f+ ^) O, U5 N( r - error("Could not open file - %s", filename.c_str());2 Q9 M, o5 S7 f* A4 K
- int filesize = f.size();7 P3 O% d9 c# v7 p4 k7 f. g, b
- assert(filesize < 16188);' L7 s' L u Q. d5 b3 w5 Z# z
- 3 g4 F* ?( w7 i3 b6 `
- uint32 indexData[4047];; ]/ h: I3 [2 g' y8 ?# H
- for (int i = 0; i < (filesize / 4); ++i)
1 V+ s2 ?3 s% v- v - indexData[i] = f.readUint32LE();
9 |( r; [* y- z - f.close();# ?% D. a6 P. }3 I/ s) ~0 C
- ; U. Y$ }% {- N3 h% b* S( Z6 I6 C+ S( ]
- if (!f.open(dest))
* j. {, K' P, v# v- l8 B - error("Error opening file - %s", dest.c_str());
2 E; S) q4 ^3 I3 T
8 A# Y6 B6 R& H X9 \( |- f.seek(indexData[idx]);" Z( ]; A3 d3 v' z) p
- byte *decryptBuf = _vm->_globals->allocMemory(2058);/ U4 n0 k: u6 K
- assert(decryptBuf);
2 j+ h5 D" j6 p; Z9 {
9 ~# f2 l8 p" D- f.read(decryptBuf, 2048);4 \3 G- n3 G- T& p, q
- f.close();: ]" ?2 [! W( X8 {& y* Y% w' F
- 2 V7 Z( F* b; @" R* B T
- // Decrypt buffer. v1 z# Y# X) L! M
- byte *curDecryptPtr = decryptBuf;6 D4 ?3 f% n4 J7 r, h% o/ o
- for (int i = 0; i < 2048; i++) {1 i' D1 Z L- S7 K" o& a
- char curByte = *curDecryptPtr;
& R- d5 q0 T3 f- ?. g, r3 O$ v3 D$ [ - if ((byte)(curByte + 46) > 27) {( y' N6 o! l* d$ }7 ] q% _
- if ((byte)(curByte + 80) > 27) {2 z$ P% g, `0 B5 C2 s
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))$ t; e& o) m. M6 s& @1 X
- curByte = ' ';4 F- i' g; n2 _
- } else {2 C' W- A0 F% f, n7 w
- curByte -= 79;% m7 U2 {/ F9 F3 D
- }
! r5 w/ X* @( j p% m7 ^ - } else {
+ H2 U4 }; ^/ ?. g7 n- s - curByte += 111;$ H) l* K/ g+ e1 u! `" _8 B
- }1 F8 R2 h! s- t
- *curDecryptPtr = curByte;
' I x; ?5 `3 D, a7 [$ S) L - curDecryptPtr++;& \) J$ w2 ]7 G# W; j- V+ S6 O
- }, Y( r9 D2 }, N+ c, v5 G
- ! W2 m5 _1 W: @" p$ d4 [5 c- E# D
- // Separate strings
+ Q9 `' H7 f2 y - for (int i = 0; i < 2048; i++) {% _7 S" L/ j* t
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)# L/ ~ }# p, a& l" ]! s! ~
- decryptBuf[i] = 0;
5 U( m! x9 Y, X - }3 @. j2 K9 C8 O" ~ t
1 i: {; i6 X) H( F- b' t% y# M- //add by shane007$ a1 g5 L, k) z8 }: [7 n6 H0 }! N" N
- //debug((const char *)decryptBuf); ~" O2 d( t0 T+ Y
- 9 t: k# X; j! r5 d" y) [
- // Check size of each strings in order to compute box width" e) J& S: @; G# ]1 y
- int curBufIndx = 0;: Z' G( ?$ e' p q5 p
- int lineCount = 0;
4 l4 D) N1 C: @# f6 R0 {) w - int lineSize = 0;
9 h2 F/ M* w+ m5 S9 C' y - char curChar;7 K/ U) g: [) {6 d3 r
- do {
0 O8 e5 t2 ?8 c/ }) E - int curLineSize = 0;- T, Y/ C( C6 I+ A' m7 _3 C
- for (;;) {3 T3 q6 D6 m- C3 n! d3 ~
- lineSize = curLineSize;: r7 ?2 n. D' A% N Q' {5 d% l R
- do {
u* t( d/ S4 a! e5 i - curChar = decryptBuf[curBufIndx + curLineSize];2 Y% Z1 I1 ^# m$ a- n* f8 u
- ++curLineSize;0 g }' N1 I6 s1 ^7 P: r
- } while (curChar != ' ' && curChar != '%');% e. B5 c4 Q* ^9 S7 D$ Z$ ~
- ( i4 w6 w6 \3 F% |8 e# E* v, t- X
- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
) E( }/ ~2 {) P( a) E - if (curChar == '%'); a7 X" }1 l5 M \: Y3 j7 B
- curChar = ' ';: J M& T( E- |, x0 |) L
- break;+ a8 M- k6 _4 f: s/ s& w) j- M
- }, A9 X- ^* Z& I2 g/ k; G
1 ?$ m3 g, W- a: Q# o/ E- if (curChar == '%') {
" @. w+ j) Z4 p- X6 j& t" d - lineSize = curLineSize;
y1 x" J' u, Z/ ^: j8 f1 V# ] - break;
; |. J, Z4 [! {, g; I& i8 i - }# g* s( B8 c# h: j) c+ u0 _
- }+ x' u4 P o6 X1 j' u
- ++lineCount;
! F, V! h+ o4 B2 }7 W$ m - curBufIndx += lineSize;
/ u* ^+ {. ~# Y# R8 \ - } while (curChar != '%');7 R G% Q- i7 a0 P8 N2 l7 X) G8 g( Y
- _vm->_globals->freeMemory(decryptBuf);
$ C5 R: g! {" u9 e, I: T - return lineCount;
, ?4 D5 B( ~% e6 C, P( f - }
复制代码
6 N7 G! ]% G/ m
8 V2 q) V9 X) I4 t7 V |