本帖最后由 shane007 于 2023-8-12 09:10 编辑
3 S) P9 d7 T9 w; H! Q y/ f( `. V1 P M5 c5 z2 m) C3 H
这游戏的字幕放在LINK目录下,分为*.IND和*.TXT 这2类文件。
! r/ y* z+ S7 q" i0 a# k 其中*.IND是索引文件,每4字节是一个索引,定义了每条字幕在*.TXT中的偏移位置。
% N9 }* k# G( Q! \
+ Y9 r& G# M9 z# i 比如,对话字幕保存在以下一对文件中,其中an代表的英文,此游戏共支持3种语言。; W! m3 L" A0 U: o* W
RUEAN.IND) o: O) b3 d$ m$ \
ruean.Txt* Y Y8 C2 C$ k) E/ t3 S3 |
; N- v" w2 y/ ]2 \8 p& j
*.TXT使用了加密方法,将字幕逐字节按照某种方式进行加密,具体实现可以参考代码。# P* d+ ~4 b/ e) Y5 L
提取字幕的方法,暂定为在*.TXT的解密代码后边临时加入一段代码,将解密后的明文输出到控制台,然后提取出来进行整理。
, k9 r, `. i6 j) a. b( c
# ~5 d6 r1 `- M! s! n" A; z4 _& S% u0 c2 I9 t! \1 P
*.TXT的解密代码如下
! q$ g E+ S& W- int TalkManager::countBoxLines(int idx, const Common::String &file) {& V6 G: g, P O/ n
- _vm->_fontMan->_fontFixedWidth = 11;1 N s; `% Q$ F
- + l n7 z4 R. t& }8 o
- // Build up the filename9 @7 R5 k7 ]7 X' }# V9 y) l
- Common::String filename;6 u) O( J \2 c% A6 V3 c9 m
- Common::String dest;
6 G' c8 k; o+ v - filename = dest = file;3 O$ a3 _9 l4 E0 L5 m9 Z* }
- while (filename.lastChar() != '.')
2 _( l) I: X# N! A - filename.deleteLastChar();
6 L; I0 s% _- e7 e0 }, B+ y - filename += "IND";; c) r9 F$ Q' v
; i& C4 N. C; ?2 Q4 y) O9 o. c, {6 @- Common::File f;
/ l0 |$ s% Z8 P! n3 V5 k9 o: B& v - if (!f.open(filename))
, D1 W ~* \6 O- I - error("Could not open file - %s", filename.c_str());2 @6 [4 S; m6 K1 Z, S1 ~4 W
- int filesize = f.size();
" i+ f; G1 Y( k1 q - assert(filesize < 16188);7 O8 H( K2 ~, f2 _
8 B" X& N; e5 c6 d) @2 x- uint32 indexData[4047];
6 Y9 A$ `! ] O2 d, C - for (int i = 0; i < (filesize / 4); ++i)
; A) z& n0 \ t1 p7 k - indexData[i] = f.readUint32LE();
H; J+ a* z! w8 R4 r& c D: ] - f.close();
9 K5 H* t: ^1 S: x! v
* U' W: H3 ]6 s* Z% F- if (!f.open(dest))' |& o3 [$ Y5 S9 N$ G# M4 }. R
- error("Error opening file - %s", dest.c_str());9 E! I H7 W6 t6 V, X
- ' b; P* E! n9 ~9 `
- f.seek(indexData[idx]);
/ p9 D; y$ c3 w. ~ - byte *decryptBuf = _vm->_globals->allocMemory(2058);% ?6 R3 `! n# v" p+ N. G8 @( P( d% }
- assert(decryptBuf);
0 \% y# v P6 s' M
* i# L8 C7 ]& |5 n7 N- f.read(decryptBuf, 2048);
+ |5 t2 e, D. _, S, ] - f.close();; X0 O' F# ?" ^
- 5 `6 U( {- ~, q
- // Decrypt buffer
) C f' v, C/ q" W - byte *curDecryptPtr = decryptBuf;
- j' C' R1 o v$ Y - for (int i = 0; i < 2048; i++) {. T( ?& ? e% t6 ~* d* ]+ ~+ e
- char curByte = *curDecryptPtr;
' F2 Y, f. r [! v6 ^: m - if ((byte)(curByte + 46) > 27) {
- B {5 {1 ~3 z# p - if ((byte)(curByte + 80) > 27) {% D- a! ?" D9 {7 ^
- if ((curByte >= 'A' && curByte <= 'Z') || (curByte >= 'a' && curByte <= 'z'))
3 X n8 P7 y% h8 l3 [& ?6 m - curByte = ' ';: L% v) |5 T* I
- } else {
/ B7 R# z! e% ~. i- V5 T* M4 t - curByte -= 79;4 m5 ~( |9 r2 z+ }9 S5 H$ E; h0 i' P
- }3 q# P; L& T q7 l% O6 Q+ F1 b
- } else {
* ~& l/ m9 X" {! e0 \8 `! _% w! H - curByte += 111;/ Q1 G, ?' {8 ]+ [" E5 y- n! B8 q" O
- }
! Y$ X" A. X; P. y( x+ ?$ f - *curDecryptPtr = curByte;
" x( M& @1 X8 C) x) e* L7 h4 j" ` - curDecryptPtr++;
! W6 B; W3 C7 g; C - }* u( k! ]7 l" I3 q* b
0 L/ e9 z, i& A6 @- // Separate strings7 ~& w5 R$ Y# }, k
- for (int i = 0; i < 2048; i++) {
" M' ], u8 B+ }, J% P - if ( decryptBuf[i] == 10 || decryptBuf[i] == 13) H6 g( m# n9 m( O0 r5 q
- decryptBuf[i] = 0;- ]9 E) u3 j7 ~. H3 \6 |
- }
) i5 Y3 C2 R9 T4 V( ~( @ - # K2 `, {% n) H$ F# B" M: |
- //add by shane007% W" S. D$ F4 p, I
- //debug((const char *)decryptBuf);
7 h5 i8 ?* |$ g
& w* c! B8 v3 I& ~1 V2 ?: d! I- // Check size of each strings in order to compute box width
% _1 b4 |" X4 j \4 f6 I4 R. E1 T- k - int curBufIndx = 0;
+ g/ O j/ R( _- [ - int lineCount = 0;
& e$ Y/ I7 [4 s5 n7 |* @4 l - int lineSize = 0;
) [, }- l& z, U4 U! J4 E3 p. \ - char curChar;4 p. ^8 v! I }7 O8 i1 v* H
- do {4 V8 R& [8 T. H% V7 x
- int curLineSize = 0;
6 d0 f8 |$ v( b- A - for (;;) {% w9 k8 Y0 |- `7 C: y0 A5 f
- lineSize = curLineSize;. T' z* U9 Q7 }0 z+ X" G
- do {- W5 ]; ^! [$ I6 r7 |3 p
- curChar = decryptBuf[curBufIndx + curLineSize];. I' U$ ?4 u/ Y B) M" h. A
- ++curLineSize;% R7 {7 Z& } s* A$ x6 [# t5 g( D
- } while (curChar != ' ' && curChar != '%');$ w- u; r% r0 ^0 I& @. e2 P
) a" V) v' i) J4 N- \* m& b- if (curLineSize >= MIN_LETTERS_PER_LINE - 1) {; F! G4 d( F0 h% _, ~ B# v/ E
- if (curChar == '%')4 f& v5 f! m& R/ C' i0 j# Z) d/ Q
- curChar = ' ';. q3 W- G9 Y! ^
- break;
' j3 z" Q/ S9 l: a% y/ @ - }
- _5 ?9 _6 i7 H - ( P. Y' m7 Y+ q# ]) U# T
- if (curChar == '%') {
7 W* m ?2 h/ \2 ~9 Z - lineSize = curLineSize;
. w ^& d$ `% N; z: b - break;
% r6 }! L, U5 G8 B - }( R) {( i9 [2 u# v: \9 f; _0 P
- }0 O* C% h8 G9 S4 b* l
- ++lineCount; I$ P. D. r- m8 `8 r
- curBufIndx += lineSize;& S# }" U! N0 F) [
- } while (curChar != '%');6 s* j5 D. v. w B& Z" L7 o
- _vm->_globals->freeMemory(decryptBuf);2 c( z- f- ?" Z2 I4 F4 i: A& F
- return lineCount;
+ `: g s' x2 a. G. Q: S/ j - }
复制代码
2 p+ @* E! a& T# c4 u2 F2 X2 D+ K; }4 S$ o. t1 k
|