本帖最后由 shane007 于 2023-8-12 09:10 编辑
! t. u$ a( [8 d7 {' e' \
* j2 R. l2 c' \, q& @ 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。: O( m8 w e: ]9 J6 ^/ y8 e. F
其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
' r* | e5 x( X7 Z3 V
9 \' D, Z. F3 d: D J3 o$ a/ S% E* f" S 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。/ g# Y0 M) d3 r0 p, O) l1 L
RUEAN.IND
& A: i1 l$ ~% Z9 V0 V; I ruean.Txt, M$ F/ @$ z3 i
% X7 t5 {, Q. ~* d" j! I( D *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
0 P% L; l3 g7 X8 w/ K: @: A& V 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。) P. q7 ]# Z3 q. E4 }& k. X$ U* U
, S, ^' S: A$ q9 ?1 W
l5 C e8 K! s" A+ d7 c8 p
*.TXT的解密代码如下
! {* Y7 o: D7 ]# J+ |! x3 @- int TalkManager::countBoxLines(int idx, const Common::String &file) {- V; g. ?- w" i; f2 c6 {, ]5 `
- _vm->_fontMan->_fontFixedWidth = 11;
7 G4 v) f* q) k& J: f
; M3 I0 \$ C+ U6 \6 b- // Build up the filename6 C% L) A$ `/ A+ H$ \/ b
- Common::String filename;
% z, M9 T7 K6 ^- ? - Common::String dest;4 n+ N) E9 Q8 Z3 y
- filename = dest = file;3 C f: }7 C' g4 e0 D6 `1 C
- while (filename.lastChar() != '.')3 u+ o9 _7 r; D2 t) S
- filename.deleteLastChar();
Q3 K. J9 \& s; M* m0 b4 d - filename += "IND";, H {- |" h: L; R; w
: o# k& ?; O- I% G0 D- Common::File f;
a- r* p# k: R% V- q) y$ { - if (!f.open(filename))! ?% X' j. `7 q4 T
- error("Could not open file - %s", filename.c_str());
# E9 `& _5 q! A* Q - int filesize = f.size();/ o: }8 D( Y) i1 R% O2 R, r
- assert(filesize < 16188);7 k% x3 v" f) L
) E- Y& j# G" A* f8 y- O- uint32 indexData[4047];
6 j& ^ \+ b: ~, t( L1 z# h' V - for (int i = 0; i < (filesize / 4); ++i)
3 ^6 d$ x7 V \ - indexData[i] = f.readUint32LE();
% ^ `$ J4 I0 o0 W - f.close();2 |" {) a# o5 ]' m2 f* W& X6 @
: V/ I. q; o" A1 q7 ^$ B% m- if (!f.open(dest))
2 f$ q) |$ N9 n8 Y4 h8 t - error("Error opening file - %s", dest.c_str());
8 y2 e. a5 {+ ?" k: q# [
[/ M: U# C1 `. p- f.seek(indexData[idx]);
! Z8 P% {' M" E8 `' L4 P - byte *decryptBuf = _vm->_globals->allocMemory(2058);
! G6 k: e0 C8 H( X# J - assert(decryptBuf);
! \7 _, x2 {4 S2 @
2 W0 I# v3 o' l8 y8 w, ^7 G/ t* Q- f.read(decryptBuf, 2048);+ G( k4 S! x8 t) p
- f.close();
% z2 k" h! n! I% Q9 z5 Q) P - ; s+ P; A+ A5 m
- // Decrypt buffer+ u. L! R# P" Z. F
- byte *curDecryptPtr = decryptBuf;5 q. D; G# M2 T; F/ b' y6 A
- for (int i = 0; i < 2048; i++) {
5 C8 z' O2 a) P8 r" ]7 L - char curByte = *curDecryptPtr;
5 U+ I0 _( u! x" Y/ Q' G- \ - if ((byte)(curByte + 46) > 27) {
( u3 l5 ?- H- K( u5 o% Z* d/ v8 |) A - if ((byte)(curByte + 80) > 27) {7 X/ J. ^7 n! q. ?1 n" g
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))/ x& a; U4 C# `4 F( [4 B
- curByte = ' ';
}0 O8 r5 G5 q8 h0 I8 s - } else {
# \* |- C7 K8 P& p - curByte -= 79;' B8 m2 i7 B4 O
- }
( F% z% v* C; B, \ - } else {
/ ^- ?6 K) g; J H2 }2 ? - curByte += 111;( x6 I0 k6 U7 D) t
- }
! V- K3 B7 B r6 C; X+ C - *curDecryptPtr = curByte;
- K/ T6 N, m3 n" D* s) y8 g8 P& i - curDecryptPtr++;
+ O; M: K: {% Q; U8 x, D' f- E - }9 a' s7 v' [+ t! V+ p9 C
- 3 Q. t3 _, P, u
- // Separate strings
6 H4 O& O) a i4 e3 d: `# D - for (int i = 0; i < 2048; i++) {
' H0 y7 q# M" c6 Y - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)! h+ x; z7 m, O9 g
- decryptBuf[i] = 0;
( [2 F/ U% V' e4 k - }
: q, {4 X2 R0 _# ^* ^7 ^* S- G$ N - 6 k' S+ s% w! v, X# e. q }3 d
- //add by shane007" [& u# o# y' n# X" N
- //debug((const char *)decryptBuf);* g1 I% t F* E7 Y J
; r4 g/ V+ O2 Y9 B6 _% L3 P- // Check size of each strings in order to compute box width0 U3 a' u5 S/ E
- int curBufIndx = 0;& U$ L/ R. Z0 D1 j' y
- int lineCount = 0;
6 G0 l/ Q2 C( p r) z - int lineSize = 0;
* x3 Q2 y. n# l$ u0 `; G - char curChar;6 n& e0 I3 m" D9 Z
- do {
$ ^. S, {8 p( P1 u0 t9 j - int curLineSize = 0;8 |2 I- s7 k! q4 G5 y
- for (;;) {/ m3 ~: h% \; U1 |! o/ G
- lineSize = curLineSize;
& h$ P. W. F2 v - do {% `. d$ I% D/ Z5 j7 Z
- curChar = decryptBuf[curBufIndx + curLineSize];9 f$ q) [7 \$ \# s
- ++curLineSize;
8 o( A( T& T2 B1 s3 q& q5 l - } while (curChar != ' ' && curChar != '%');1 E. p) ^+ N7 ]3 D8 w, Z+ D2 Y
. d$ z t) i3 x7 p5 t2 m- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {8 x6 R' A' F8 j G1 G0 X/ F: m
- if (curChar == '%')0 P r/ n6 V7 N: c5 Y1 O! j
- curChar = ' ';2 U/ u& ^1 w2 Q9 P
- break;
, r/ O, V6 ~# g+ m! i* g& W# q; o - }
0 s4 p. D9 [: G- [7 V% b
, B# N5 l5 T A7 L2 _* B- if (curChar == '%') {
/ ]: V3 d( ^: ] - lineSize = curLineSize;
, ]6 w! w/ C4 m. c n# K - break;
1 x0 X# e( n9 ?3 p. Y - }
: _! D: {5 d1 N- G* E U - }* t1 ], ?' A# v7 I3 g' J
- ++lineCount;! p' B3 v3 ~& W; ]1 Y" ^2 Q! \( X" p
- curBufIndx += lineSize;/ X' h( f+ N- N" d, u# s, C8 C
- } while (curChar != '%');
5 A! F* s7 M' T6 X" N" g# F6 [1 G - _vm->_globals->freeMemory(decryptBuf);
& i& j( B4 K3 D- ~4 u - return lineCount;
) y% m. C2 ]% Z2 E2 |+ u$ W - }
复制代码 ' E3 W5 d3 D3 v k7 t
2 ]% p/ i$ b0 Z- b8 X- b: ]$ I5 F' _% X |