本帖最后由 shane007 于 2023-8-12 09:10 编辑 9 K' m0 Y+ O8 ]* C; i$ v, @" J
# h5 d- | ?6 r 这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
% c0 d1 V' D* i* Y5 k' I" [/ }7 ^ 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
) R' t- I2 @: W6 w$ m) o8 N. ~4 k) C/ P: t
比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。4 q2 S" {# @4 f0 P2 o+ ?8 A
RUEAN.IND
, b- y, h4 P8 U8 ~! m6 F ruean.Txt
* r3 s8 w4 X! n8 ]6 |! I) ~2 T' k
6 L( c2 h0 `( ^ *.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。
9 H2 `3 t, f/ z; c0 b4 l1 { 提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。, g' d: W/ B! R) t* N3 z
+ y3 T" I4 q" e/ U: `/ ~% U
y( ]6 p* h& b *.TXT的解密代码如下
; @8 A& \6 K) K K' p8 B- int TalkManager::countBoxLines(int idx, const Common::String &file) {
u, i, d: V1 T5 t - _vm->_fontMan->_fontFixedWidth = 11;
* s, j) F/ w6 e, a3 ? [/ g6 p
9 V3 g+ _" `; d) R7 G. ^; i2 F( r- // Build up the filename8 U" K% Y5 S& I# ]: @$ K6 b
- Common::String filename;& [! C. `& i* d& n# F
- Common::String dest;) B& H/ F' x, A6 z4 z
- filename = dest = file;% O; V9 p8 e: \3 i. R
- while (filename.lastChar() != '.')$ _, Y6 Q# C) T+ o J+ t# `* E: M; l
- filename.deleteLastChar();
6 e9 S" b7 @+ F* d/ b - filename += "IND";3 ?$ }6 u) B: w
- 8 h6 q! u4 K- l5 j4 @ m
- Common::File f;
: h7 z. ^# @9 Y% [2 N/ q( j - if (!f.open(filename))
6 F& f+ B/ ~# W% P7 Q, i - error("Could not open file - %s", filename.c_str());9 y3 `- L; T* C T5 U# R# u
- int filesize = f.size();
5 R! H% S% M5 \' K: e9 [ - assert(filesize < 16188);
# ^$ y8 P% d R* {
: q3 s9 u* W! u8 }- uint32 indexData[4047];$ b- _' ?9 r6 n; ~% N; {
- for (int i = 0; i < (filesize / 4); ++i)
" x: f# t, ^7 f - indexData[i] = f.readUint32LE(); R( j7 Q0 A8 B; d" k3 c* C S: ^
- f.close(); w) l7 @+ L q5 i5 X& a
7 b/ C* q0 J7 f2 N# K7 ]. Q4 k+ W- if (!f.open(dest))& H R0 N, U9 J/ i
- error("Error opening file - %s", dest.c_str());
& P7 p | T3 i6 B: r- r: _
7 ^# c) }5 y* a) T! a4 A5 ~- f.seek(indexData[idx]);
- x$ A/ ^* l# k% @0 \7 D - byte *decryptBuf = _vm->_globals->allocMemory(2058);" { `5 {) Z" J! Y! \
- assert(decryptBuf);
+ k q9 Y' {9 e) ^$ A$ W4 d4 I - + N( m& u+ q' X0 |5 |# g& Y
- f.read(decryptBuf, 2048);
0 @7 P O5 w/ @3 p v* R. n7 c/ L; F - f.close();, e0 K3 v3 _* j L
9 x9 R/ O* I- y/ q6 D/ K% t# `7 e) w4 q- // Decrypt buffer
* y- X3 T8 ]9 b9 O+ ^8 u% c - byte *curDecryptPtr = decryptBuf;
- K& H4 d: D* h - for (int i = 0; i < 2048; i++) {# d* R4 M8 l- C) r7 Q
- char curByte = *curDecryptPtr;! D* }9 M1 O3 h1 l
- if ((byte)(curByte + 46) > 27) {
: v% g8 p) x: m; r6 k* O - if ((byte)(curByte + 80) > 27) {8 Z& X3 U4 k$ w, N4 p- d4 U* R& e
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
( I, K6 i A! u* L0 G7 ] - curByte = ' ';
: A9 v& f3 G' Z* a% \$ Q9 `8 E% E - } else {
/ e6 o8 w3 M1 | - curByte -= 79;, L u7 N2 |$ D* f0 Q. I8 h) \
- }$ d5 B. b% r4 Z' g
- } else {
* R' N; E. ^) s# S. Y+ f8 @1 K5 { - curByte += 111;
% z# u2 k6 ?4 R0 U! d4 k6 _; B8 z2 _* } - }: U! r% o8 b) Z, B& [: ~$ L
- *curDecryptPtr = curByte;9 Z& _1 N! h0 Q" L
- curDecryptPtr++;
; S# U5 O: R. A7 Y - }3 ]0 e3 d+ L) J' E8 ?. E7 W
- - k, \# F% \' g2 O4 c# P/ t+ [
- // Separate strings0 F9 v5 g6 Z# p: b+ f; B
- for (int i = 0; i < 2048; i++) {+ Q7 z% B6 E" f9 ^6 p* q# N
- if ( decryptBuf[i] == 10 || decryptBuf[i] == 13)+ i+ t5 ?5 b, Y1 D- }+ a; s3 C J
- decryptBuf[i] = 0;
0 y$ \ P$ ^( H - }
' x- d" c3 F& `1 C* o - 6 h0 s6 F1 X2 D z% s* F" u2 {/ S
- //add by shane007
0 g# D- x |* y; v4 _6 L: k - //debug((const char *)decryptBuf);5 t& \' J* C; M; x. Q7 j
- 1 M# F5 a$ [9 Q( ]3 N l) [$ o4 Q' G
- // Check size of each strings in order to compute box width: o% a+ g* l% y) M1 D7 ]% E) |
- int curBufIndx = 0;
" t! I2 w! `: R - int lineCount = 0;
! E4 p5 x9 W6 q9 C - int lineSize = 0;
0 d) w% K$ L$ B2 `! z/ x - char curChar;
+ d5 e1 W) C2 e, c( { - do {0 Q9 ]: ^, p# t& _
- int curLineSize = 0;
2 l) C6 M7 m6 K: I; s3 Z2 v - for (;;) {8 E8 o1 |9 D+ `) [' K2 E: f! ^8 k
- lineSize = curLineSize;
/ k* f4 N& \$ r - do {
5 D6 Y2 W$ B5 B) q1 v6 S0 L' h - curChar = decryptBuf[curBufIndx + curLineSize];
. ~9 l+ p& b4 a& e" O - ++curLineSize;
; O j4 S( w9 X H9 A' v* L - } while (curChar != ' ' && curChar != '%');% U; o4 L7 t! }. q- |
5 b0 f% C7 A0 x* a3 `( Q0 Y: D- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {6 O' W* a0 i$ R, E* q
- if (curChar == '%')
2 H: z& [" k$ |* q ^* e - curChar = ' ';* N- o: {9 i7 x: J j
- break;) S- K- v- h x7 F1 F2 ^4 U7 w
- }- k3 E: b; Y% b, c1 z% v" s
( e8 X$ ~# L3 N& z% c& U- if (curChar == '%') {, p7 c( v8 |. S/ r( g7 a5 X
- lineSize = curLineSize;
4 s' w# s4 r7 v! r; t - break;" f; K z4 q+ B) Y
- }' N% u4 V/ O$ `8 k7 ?7 V# ^! G
- } H5 z0 z- d& y' a. p; X
- ++lineCount;6 B' Z; t: A7 c% Y7 `
- curBufIndx += lineSize;
* q$ f: ~) P6 ]' }8 E$ r% w* g% s& Y$ i - } while (curChar != '%');. |3 Q+ r! X$ X$ h1 _9 i) h% _* g. P; h
- _vm->_globals->freeMemory(decryptBuf);
' T5 C' E" X- x/ w8 k7 ~8 X - return lineCount;! b o; y3 O" I" T W! t& F
- }
复制代码
9 z6 O: F* Y* ^1 i& E* ?) S
7 J( s0 q/ f1 S" Z) C) v \, W$ T4 ] |