本帖最后由 shane007 于 2023-8-12 09:10 编辑 , L' k& A N; _/ h: W8 x( W
8 Q; [ T6 H/ |$ m6 x6 |! h 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
/ u" B- F/ L- o! [' i$ r9 T% |: z 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
) J( z, C' L$ G) {% l9 b* `
9 r* I- j7 J# {9 K4 W# h5 W 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
l* X8 G2 w ]6 I* _4 a" D# L. Z RUEAN.IND
: s1 U8 b2 W5 }! j' z0 ?3 b1 \ ruean.Txt
`% b) m$ C0 `+ x$ Q" N8 j- J7 V+ C% N8 s! g" O* c# m
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。" i1 `' R3 T; \' w+ L" \* _0 O
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。1 R/ c* q. F$ v; N* ?/ D" |
5 c! [( ~0 r5 c+ \1 F8 ?( a5 d
! g- r$ G4 P G, s *.TXT的解密代码如下' p+ V7 a6 b+ }" g6 w9 [! n2 T( w
- int TalkManager::countBoxLines(int idx, const Common::String &file) {( S7 u$ {5 P4 s6 _
- _vm->_fontMan->_fontFixedWidth = 11;* \' q4 c! J& d
- X( [1 B8 M3 ? e1 I
- // Build up the filename
9 \: c( s) @# ]! O% B' S- P" D# g - Common::String filename;
6 x4 ~3 y+ L1 P8 O/ c5 K; U I, { - Common::String dest;
, L# K4 G5 E2 e7 q - filename = dest = file;0 M2 \8 Y9 }6 T
- while (filename.lastChar() != '.')
7 ]$ N5 s/ O7 i% q - filename.deleteLastChar();4 ~5 v V1 m4 B' j5 K" l- A
- filename += "IND";
* N+ E5 s% S8 W# `2 _4 n
L. @: K1 x2 l6 D- Common::File f;0 J& C: Y/ G/ c! y$ u) P0 |: Z% b
- if (!f.open(filename))
. K2 Y6 @! a% o! z5 ` - error("Could not open file - %s", filename.c_str());/ a+ i6 k) h9 ]# ^- ?% q
- int filesize = f.size();4 }: G+ I% [! L1 H# ?, i: U$ Y
- assert(filesize < 16188);
; z/ W5 |; T2 g) v/ G2 S - 5 _% v' F! P, V8 C
- uint32 indexData[4047];
* b8 a3 S6 n! Q3 p+ r* m( X5 n- l - for (int i = 0; i < (filesize / 4); ++i)
- [0 a# g. Q5 j- G/ s$ V - indexData[i] = f.readUint32LE();% S( `. m! f, t2 K
- f.close();
5 Y9 h8 P! w) m! L' d: [
% [4 N/ }% f/ T0 U- if (!f.open(dest))$ i5 ?! c% M h& I
- error("Error opening file - %s", dest.c_str()); ?) g$ {- J( ^% x) K* o, u# C
& O# `3 B5 z# k% J z- f.seek(indexData[idx]);
3 d" x' f& c p0 Y - byte *decryptBuf = _vm->_globals->allocMemory(2058);
) E) x3 {! D, m - assert(decryptBuf);4 B6 ~" ]- b9 c* |
- 0 `7 W" N! E9 r) S# A) S
- f.read(decryptBuf, 2048);
; j! ?: \- B9 `2 M6 F1 I) l - f.close();
0 u- I" V" W* ?% R1 Y- @
" D1 L" b i8 K" \0 e1 w- // Decrypt buffer! f3 \! ^' L$ N2 p$ |
- byte *curDecryptPtr = decryptBuf;9 R0 k+ P! ]* u. {+ y) K9 ]
- for (int i = 0; i < 2048; i++) {7 u0 K/ [7 o- F. J' {6 W
- char curByte = *curDecryptPtr;4 C* U6 \6 T* g7 ^ J
- if ((byte)(curByte + 46) > 27) {7 v( d. U: B' c+ w6 }4 }
- if ((byte)(curByte + 80) > 27) {
" N9 U: I/ U+ D4 \7 E - if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
, i% V/ W: A2 R% R' V - curByte = ' ';. z/ z" V- w# l% I1 T
- } else {. W6 k9 l6 X2 U; U$ h
- curByte -= 79;
0 `( r* R& _6 W4 `9 F U - }
B) B9 r2 G: T - } else {* v( T1 q; w( J' k# [
- curByte += 111;% `. G1 |0 d; k, B
- }* r8 @+ F- M7 y7 r j, v: Z; d
- *curDecryptPtr = curByte;3 N+ t% x6 h. m& ~
- curDecryptPtr++;
# F3 S* D$ h4 q - }, v+ Q' j6 g: V: u
- 2 _8 Q% a* G( H
- // Separate strings/ l2 l3 ]6 R) i0 ?5 r
- for (int i = 0; i < 2048; i++) {
7 Y @, J9 Q$ D; d6 ~$ o7 c - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)3 ^8 D% ^! M! F3 l( a
- decryptBuf[i] = 0;$ R( `1 C( O. a) N' F
- }! F3 |* C& n8 {) i3 M
* c) I1 t( W8 o! z* L- //add by shane007
2 O% p, |4 ?* Q n8 ^4 j7 | - //debug((const char *)decryptBuf);/ i, a: b$ s- X
9 A- v* y% o1 L% T u- // Check size of each strings in order to compute box width# y# O6 y* w. \3 ^9 |0 }' V/ r
- int curBufIndx = 0;6 e. x; N9 |3 t- x1 {/ M
- int lineCount = 0;
8 s, R( i! Z4 K! X1 L& Q - int lineSize = 0;
+ T& l p: R2 e) a% b - char curChar;. ]7 a4 [" y& n2 K2 V6 c
- do {" g0 C# [# |; }; X
- int curLineSize = 0;
" {1 a4 I* y8 ^- V9 F/ ~/ A - for (;;) {
' F2 p. _9 Q9 a. a, E8 k - lineSize = curLineSize;) D) `" K% A: F$ h& ?; r% }! Q" n
- do { b0 L( r' g: ^- ^0 k/ O
- curChar = decryptBuf[curBufIndx + curLineSize];
8 ~1 I) k) T" X0 P/ m - ++curLineSize;
8 _9 q. ]9 u6 B, I1 t0 e4 x# h3 `* h4 c - } while (curChar != ' ' && curChar != '%');$ h2 y6 B4 o$ }; ^
- / a! F+ A# n1 w4 e& u- J( x
- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {) g4 P! Q' @4 G3 s/ ?" r
- if (curChar == '%')
% x3 {; A# a3 P; Z$ d - curChar = ' ';; G4 K, g! i9 n+ \3 A: f
- break;7 ?* q" y& w) K, m8 v& m8 f) U8 P
- }
: I! F- ?$ I6 L V - ( _, |) o# W' D, c) J: G$ N
- if (curChar == '%') {9 s1 \$ |. { i2 x+ t& b
- lineSize = curLineSize;
/ m& c. ? p [! G4 u0 c - break;
* a/ u1 p9 m7 ^ - }8 |. A8 x3 ]/ c$ x% T
- }6 j0 W9 ]0 a8 }( V
- ++lineCount;2 M: t, C; E( z
- curBufIndx += lineSize;
, v0 g0 v3 P2 }4 w - } while (curChar != '%');
- K8 ~. w0 y: i K; l \ - _vm->_globals->freeMemory(decryptBuf);
# J9 G4 E9 R1 _; [9 t - return lineCount;1 m( r" F4 r+ e* Q" b
- }
复制代码 , U: { d& R4 V1 n- i Q
) i* p/ G% g5 h8 m
|