本帖最后由 shane007 于 2023-8-12 09:10 编辑 1 r8 G! m) c# R5 `' l, G/ H% T
9 B, m' G9 Y7 Q; o 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。: o B7 p9 Z, s9 P
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
5 }2 ` I) J( _4 b/ f% r
+ y& W; {" j( z! h, J6 Y1 a 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。
2 r2 K3 \! A# g9 L @: X RUEAN.IND9 u9 n N& z1 T! @( t; }' p
ruean.Txt& a& E! c+ u6 S$ x3 J- e
R8 n( l7 K! q
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
: T M! }5 ? x0 E0 t2 Z9 q 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。4 L0 B' q4 V& P% ]4 X
& a, {# G$ T$ T8 w8 q; x
% r8 P; R$ O9 R+ E *.TXT的解密代码如下
' p. Q$ n, A9 m# z& _- int TalkManager::countBoxLines(int idx, const Common::String &file) {* }8 X/ t3 L& \
- _vm->_fontMan->_fontFixedWidth = 11;/ A( @$ I$ Q4 T7 v$ i# P! P3 n
4 g Z; D a8 `3 g- // Build up the filename
: K6 p' v1 @" C5 _$ c: ]/ x6 W - Common::String filename;1 `; k- S" \: N4 J' x
- Common::String dest;
J5 p, \0 S7 }" f - filename = dest = file;
( Z3 I6 c6 D3 P - while (filename.lastChar() != '.')
) E0 c) m! D ^+ d5 ~ - filename.deleteLastChar();0 Y! B% W! L6 u" b' T
- filename += "IND";
6 O; Y( C# y% O9 i
% T6 ^2 |% \( e+ I0 z7 r- Common::File f;% d6 d$ |0 m6 h
- if (!f.open(filename))) z. ]% {: a- E1 e1 J1 Y1 m) o
- error("Could not open file - %s", filename.c_str());& t8 Y" y& H% y+ i- j, h
- int filesize = f.size();, l9 Z* I# p% H- z
- assert(filesize < 16188);/ }0 ^2 H7 `0 l( b: a
- * y( i" Z- T- Z$ |6 x9 c0 d
- uint32 indexData[4047];" N$ C& u: [1 a V8 l5 n' ]
- for (int i = 0; i < (filesize / 4); ++i)
7 A( O' \: U$ G# e9 y. z - indexData[i] = f.readUint32LE();
' `3 e9 S7 j+ D- j - f.close();0 ^6 o" g" T# r. [% d- L3 ?) K
# u" E! N' ~" P u- if (!f.open(dest))8 `/ q: z( Y9 G A& l
- error("Error opening file - %s", dest.c_str());# D4 K7 M0 }; ?1 t
1 r1 Z. t% J9 x2 X- f.seek(indexData[idx]);5 S3 \* S9 R7 ^$ X1 y: e6 B
- byte *decryptBuf = _vm->_globals->allocMemory(2058);
; D% c& P) Q! p7 ]0 V; A+ g - assert(decryptBuf);
1 A9 I( H. U9 P6 i0 L, O/ l; X - 2 _* f6 ?9 z: i
- f.read(decryptBuf, 2048);
! \ j% y( \: o7 q* S: Y - f.close();
$ w( N3 t9 b0 v9 X
* w+ y7 }% W7 `, Y0 V3 @- // Decrypt buffer7 I/ Q: ~) V: N: o- T0 u/ k
- byte *curDecryptPtr = decryptBuf;
* p& Q+ D) P9 U2 G0 g U0 a0 X( U B - for (int i = 0; i < 2048; i++) {2 e" p2 B! s. Q$ H
- char curByte = *curDecryptPtr;: `& ~4 x3 r3 }+ I% R
- if ((byte)(curByte + 46) > 27) {8 f4 U+ |6 N0 I- h
- if ((byte)(curByte + 80) > 27) {- I1 H/ D. j! Z
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))* V. [ T5 n& u/ b' q2 f0 F
- curByte = ' ';
, T# P8 H( U% [5 [) { i - } else {
9 l3 v: @- ?' p: {8 h: f: U - curByte -= 79;5 N4 K7 c3 t h' p) {. E, J
- }
3 }7 i4 ~; q. U% e2 V% Q - } else {& a+ _7 ]' g! `/ J7 F
- curByte += 111;
* X# `3 ?% W1 F' \ - }
5 D) P6 ~$ k$ O- Z7 k" E - *curDecryptPtr = curByte;
/ h0 a- Y/ O! a$ U; i - curDecryptPtr++;4 [/ v/ i* ?$ I1 o0 u" F
- }& E* T9 p# U+ T
/ k: j/ C! \" n8 f4 t- // Separate strings- |' ]4 \" z& p4 x* W; d$ E
- for (int i = 0; i < 2048; i++) {
; p5 l" ^2 p' s' K - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
* C( ^7 y3 n. ?7 v* D - decryptBuf[i] = 0;
* ]5 I! G% ~0 Q8 `6 A( Q - }
8 n3 ^6 l& E" F; y' J) f' {# j- B
s2 i! J- ~7 p+ ]9 v8 O; C$ I- //add by shane0076 ^3 e1 x5 v4 K: D# v
- //debug((const char *)decryptBuf);
4 |* U, Q6 d1 X) j' e3 t! ? r3 m - 4 s5 `4 J! \9 ?5 a8 o y
- // Check size of each strings in order to compute box width! J b" {; d8 O* U( |. z9 a
- int curBufIndx = 0;
0 g+ i2 N7 X+ ^' [. c' \6 G - int lineCount = 0;
6 c) T8 C9 S! a6 z2 T - int lineSize = 0;
) I. w2 n. J# L. Y9 S+ h1 j - char curChar;: ^3 x# L$ r$ N& i0 Q! [! B
- do {
) y; Q! T# u4 u5 e3 O2 z - int curLineSize = 0;
8 V: Q) m# V7 N0 ^3 ] - for (;;) {
; b, y2 v( y1 S6 h! k' h8 V - lineSize = curLineSize;
- \: d$ ^7 X' Y9 Y8 ] - do {8 R) l) ? a4 P3 o
- curChar = decryptBuf[curBufIndx + curLineSize];
/ V# \- v ?0 L0 O# r& R - ++curLineSize;! ^; d& e4 V, h) W8 y) U; c
- } while (curChar != ' ' && curChar != '%');" b4 p& C V9 c3 [- I) p
- 8 i* L1 v9 m+ f5 @6 Z$ _$ @
- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
4 L% X* A6 G' [. a' l - if (curChar == '%')- v( g# `0 P; D" g. y
- curChar = ' ';5 n/ P- B. b% O
- break;- h2 T3 }% _$ T9 R/ @/ r
- }. r8 e1 H4 x* _" H: B+ a8 t+ a5 {6 F
) h n0 t! j& @: M. @- if (curChar == '%') {$ Z: z, D. K- U3 h; _1 \* o
- lineSize = curLineSize;% K ]2 v6 ?) T4 k7 @
- break;. V4 A2 |; o+ D
- }7 g" p# A; F/ {: j
- }
* P# u$ x3 h; F: d# Y3 }6 G - ++lineCount;: U9 {7 l Z% e
- curBufIndx += lineSize;6 _6 W$ n7 j6 ]& d; M
- } while (curChar != '%');
$ l( g$ A* k9 Z/ A2 ~ - _vm->_globals->freeMemory(decryptBuf);
: ^% X0 _7 \5 l6 _ i, d - return lineCount;
' U7 D8 |0 }$ O- p' t ^ - }
复制代码
2 M1 G7 n3 `. v
0 H1 L$ d, m& P* K# k$ ?8 M |