本帖最后由 shane007 于 2023-8-12 09:10 编辑
! d0 W' }; `3 e9 A% o& Q/ S
) B9 V/ t. g( c) J% t4 l6 L: T 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
/ w9 E% I( x' R; X* k4 J 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
- H' X; `6 a1 }& x5 X
/ o3 F* b3 d. k3 j8 Z8 p3 \ 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。, D8 {0 G' e0 d2 M# C
RUEAN.IND
7 G, Y$ U( l# J7 Z+ O ruean.Txt0 I' H$ p4 L' q, s, S$ b8 V- v
: q8 C" d( M- Y4 E *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。- T3 M* J: j; ? R
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
) z5 o l* F' G- V
" Q+ T3 b* K d0 j1 i7 k c; g0 r [
*.TXT的解密代码如下
% c l; T+ F4 }* q- int TalkManager::countBoxLines(int idx, const Common::String &file) {
: b/ R7 X: Z: F# g - _vm->_fontMan->_fontFixedWidth = 11;2 I( ]' [" A' h
- ' k9 @. ?7 l, C$ m, i: e
- // Build up the filename: v0 T, V7 D) O+ O
- Common::String filename;0 |. i: Z, a" A. u% X T5 F
- Common::String dest;+ s, P! W+ y4 Y" e T% r1 p* D, m
- filename = dest = file;( k7 G4 } q0 i3 t) J/ t
- while (filename.lastChar() != '.') W* ]# G5 d8 r4 ~1 E
- filename.deleteLastChar();
% d* e2 }2 q5 {1 G' K( j6 _ - filename += "IND";
1 n; n7 q, q: d$ D2 o; \
+ V9 X8 w2 C; ^6 r9 i0 E- Common::File f;
$ v3 z" j$ L' v+ b' N& | - if (!f.open(filename)); R$ A2 {, c& s+ U' n4 q% |$ f( c
- error("Could not open file - %s", filename.c_str());
/ s- H# L1 y" H0 g - int filesize = f.size();
% G( h3 ~+ [% w# [1 L* Q - assert(filesize < 16188);
% e3 @( o/ K- q* z; ^) x. g$ w - " e7 a, E3 {6 x3 v9 j+ f: V
- uint32 indexData[4047];9 N/ e* l4 O' b
- for (int i = 0; i < (filesize / 4); ++i)( t! W. e- k6 @# r' `. R
- indexData[i] = f.readUint32LE();1 o, r) T+ e5 [( p
- f.close();: h3 Y5 \9 m6 h. V* X4 K g
- 3 d' I9 F9 a) y" r5 S( R% ]/ O
- if (!f.open(dest))
+ @; @ D2 `; I% C( e - error("Error opening file - %s", dest.c_str());, u) i8 o# l; Q5 ]( i
- 9 j0 s( D/ B" A8 ^
- f.seek(indexData[idx]);. P& u* ^' J' P; l
- byte *decryptBuf = _vm->_globals->allocMemory(2058);
& P: p: t4 g) R2 V+ L, L - assert(decryptBuf);
: t, ]# m0 `9 R! d1 {' \
8 p% \) T2 O- H0 K- f.read(decryptBuf, 2048);6 x. C6 D( W o+ {# ]7 ]) D% k1 c9 i3 |
- f.close();# O" U7 a/ P- k" V r; v* T& Q
) V8 \9 j$ u; C: B2 p/ Q- _- // Decrypt buffer% _- ^. }5 q2 B
- byte *curDecryptPtr = decryptBuf;, H* \& N- d7 `1 Y, {
- for (int i = 0; i < 2048; i++) {
* T* P: f4 N2 u, N: Z - char curByte = *curDecryptPtr;
# r, t0 k3 X$ L c9 o2 P) Y1 a - if ((byte)(curByte + 46) > 27) {& \- D) s" S3 N" ]- F7 f: U6 \$ B0 T
- if ((byte)(curByte + 80) > 27) {8 y) }, u2 z3 B& ~# b, P2 A# A
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))1 q; O7 C2 O) q1 X- A
- curByte = ' ';
5 a. x7 D$ h( N0 u - } else {, s1 k9 a$ ]* I/ |+ s6 M4 R
- curByte -= 79;
& t& I+ X9 h* I! e& e- g - }; E9 j. K3 Y9 C/ h! t) {
- } else {: V( N* R$ N( Z
- curByte += 111;" x8 c& |5 R2 {2 T
- }
; ? L0 t% E0 t - *curDecryptPtr = curByte;9 M# Z8 B' o2 y7 B5 @
- curDecryptPtr++;& K* i/ ?, Q/ d/ |* A ~
- }
9 ?7 j; G6 Y/ }; S9 Y5 R% g - * N; D: @9 b4 {$ n1 [8 j1 c
- // Separate strings; F% \7 p2 N+ U$ ~
- for (int i = 0; i < 2048; i++) {+ _# c2 n/ r# A2 L
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)
( h+ f1 M/ j3 r+ K- Y0 _ - decryptBuf[i] = 0;
! k/ ^- T/ @7 T9 l$ T2 N - }3 T! a- \# r; i: W6 M. b
% M+ a( }; w; ~( n g0 F, n- //add by shane007
0 q/ ^9 Q6 {2 @# G2 e' b - //debug((const char *)decryptBuf);6 z: K5 S9 j2 u( ?) r5 _
- 1 f- r9 q) k; F$ h; d- u4 {( B# t, p- x
- // Check size of each strings in order to compute box width5 j" @. w/ h4 }9 o' K
- int curBufIndx = 0;
2 {6 A& S. r/ ^0 d* o+ T - int lineCount = 0;
$ ~ |" @; W( l9 e9 b) [7 s - int lineSize = 0;
% v# \: |$ P# G4 \. I/ ?$ z - char curChar;. u$ F% F: [* l+ F$ h; E$ C
- do {
1 d t {: {3 c, P7 K! o - int curLineSize = 0;" U' D3 n j: {# T! ?( V) w
- for (;;) {) [0 I3 z) c: Y
- lineSize = curLineSize;" K/ t4 j9 T1 m, k
- do {; A0 j) @- Q! {0 [, m% _
- curChar = decryptBuf[curBufIndx + curLineSize];
4 v9 T0 e9 D6 F1 q1 _3 D - ++curLineSize;
7 l% k1 j7 O8 Y% {1 N" \ W - } while (curChar != ' ' && curChar != '%');: m" S0 V7 O7 X3 `- ~
- % l1 b) b6 {) l3 K. f4 e
- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {
6 [1 r# J, o+ Z6 b2 z2 z4 h - if (curChar == '%')
5 @" w+ ?6 A" I$ a) B - curChar = ' ';
* [: ~9 X8 g& s" _ - break;. p$ L9 X) a; h+ w$ R I
- }+ R) W# ?: {: W+ `# q1 I% x0 [( V
- ; H4 J/ n& n6 A( ^. Z
- if (curChar == '%') {
. r8 B# s9 B3 J% ], a7 ` - lineSize = curLineSize;+ e( s, J( [5 h. K) N3 V
- break;
" o! K0 K2 x+ W7 Z& w - }8 z& x# ?! b- S% W0 T' K
- }
6 ?( i4 D6 W$ p/ P9 p - ++lineCount;; O2 o6 @% [) l3 c+ Y
- curBufIndx += lineSize;7 \7 _, a% z7 N) B; N# }
- } while (curChar != '%');9 ?$ f, y1 i$ `8 Z
- _vm->_globals->freeMemory(decryptBuf);% @( q. a3 r$ ]5 a
- return lineCount;( F/ f3 w/ ~; E/ V3 z
- }
复制代码 + S# _6 s7 t$ ]- E4 ]: X
* |: [( R D+ c5 z
|