冒险解谜游戏中文网 ChinaAVG
标题:
【Scummvm汉化 #3】The 7th Guest 第七访客 #1 字幕篇
[打印本页]
作者:
shane007
时间:
2023-8-12 13:38
标题:
【Scummvm汉化 #3】The 7th Guest 第七访客 #1 字幕篇
本帖最后由 shane007 于 2023-8-12 13:57 编辑
+ T* B. @: J7 B, }+ e" R# P5 @1 [
7 s' f" @/ m! J" f# Y+ Q9 K, ]+ T
这个游戏原本是没有字幕的,但是在Scummvm论坛上发现了一个帖子,
5 a, `1 d: {7 [# W! k
讨论的内容是关于在原本没有字幕的游戏上加上字幕。(最初的缘由,是为了帮助一位失聪的朋友)
$ v9 Z% l5 ~% ~5 ^, S0 p
https://forums.scummvm.org/viewtopic.php?t=7168
, z/ K, }) l# e4 m' l2 t; O" _
[Scummvm-devel] Displaying subtitles in voice-only games (narkive.com)
( _4 X `1 G1 E5 D; Q
5 }; X6 [( e% u* O }6 ^ a
前段时间第七访客出了25周年纪念版(The 7th Guest 25th Anniversary Edition。
! K# Y6 O) J$ S- S, w: b% i
在这个版本中,游戏的视频是有字幕的,因此把这个视频的字幕用到Scummvm中就成为了可能。
8 D. u D2 h1 `" c" q( H7 J
1 j% D/ n! R, z& p7 [
我查看了一下最新版本的Scummvm的代码,发现老外已经加入了一部分代码。
- C0 O( p& r# {( J. O O! I0 f; o
在此基础上,汉化是大有希望的。此种汉化方法,也是前所未有的,如果真的实现了将会有重要意义。
4 J9 f3 M T: C; j& H& m$ g
$ }1 k* h9 @& H- ~+ x# r& Y
类似游戏还有
· Groovie
/ O& Q l8 o9 m6 T5 W Y$ r
- The 7th Guest
9 ^: a A& |; y, H' w; R, M
- The 11th Hour
+ j1 ?! J8 g7 c# z
1 X/ j% |" h' c) B7 _& t4 t1 B# h v
· MADE
7 W" G* j( e: d( x' {
- Return to Zork (descriptions are text only, while spoken dialogs lack
, x5 y" Z D0 ]0 n6 x1 ^$ G6 ?3 J
any text)
3 X6 ~3 Z- h, m" ~4 |3 v- g
) h6 H! Z) ], r
· SCI 1
: d r8 n8 C* ?' n( {2 p
- King's Quest V (CD Version). In this case, just enabling voice and text
3 n# O7 Y. y! }2 s9 n' L
simultanously would allow a 3rd party to create a set of MSG files
1 T9 L- t3 W- n
containing the voice transcription/translation, as it happened with Gabriel
( }: t$ i/ r+ W- ` Q0 y" T
Knight II.
0 Z6 b, @6 a9 k- C7 }
" o1 O7 P) Q W7 w: p f& P: Q
- N. B' A# R! G2 G! D# S
Future engines:
4 N# o+ r: L3 V: D! q- K9 D
, r. h3 r( Z/ q" d+ q: W w R
· SCI 21
u* A3 {1 [4 C
- Gabriel Knight II: The Beast Within (Already a fan patch available in
! h& Z/ \5 U3 v% k1 ?
order to enable the text display feature)
( z! Z6 A( i7 J' }! B4 y, z2 C4 r
- Phantasmagoria
$ {0 G1 z+ T* U# `9 |2 p6 N
- Rama
/ R6 l/ N( S- D0 s; e
- Shivers
" @; f+ D: q4 J& ]$ p. L% ?+ l
- Phantasmagoria II: A Puzzle Of Flesh
3 A- O8 B; p2 P3 U" L! z
8 P- L" u& ?2 u
· SCI 3
2 F' q6 E3 k' V" X. h% J
- Lighthouse: The Dark Being
; C' { @6 y, C- V: V9 D
6 M" [% b! o3 w
· M4/MADS
/ p/ n( b0 [! |* ~& W3 D7 J
- Orion Burger
: N) w, O% Q* M5 \* T
4 G# p- ]" Q6 g
· Mohawk
+ P3 ~0 T1 R( i, m$ p8 X, S j
- Myst
; i' Y0 G u# p
- Riven: The Sequel to Myst
复制代码
3 i R3 h! c- E7 _6 }( Y. c- m
! Q* ^9 N- N+ ^3 w
5 G$ I* ~2 q8 A. Z' x3 G# W' q) T& _
2 s' ~) a* p- V/ a- x, p: z
相关代码如下
& c+ B2 z- `5 \. f
bool VideoPlayer::playFrame() {
' C5 @' p& V, e1 q1 D$ t" g
bool end = true;
y; T2 {6 \& u& g% p
& F. q! \9 c, ^' y2 K
// Process the next frame while the file is open
; T; X( {4 i6 \/ u' u7 ]9 d& I
if (_file) {
7 b7 J) t% |0 r. q! i$ ^
end = playFrameInternal();
& P) H3 i) o8 F0 c/ e' Z. d1 y- U/ r
0 ]0 Z; I! Z- S# } E/ [
_subtitles.drawSubtitle(_lastFrameTime - _startTime);
! j8 }1 N; L& g; ^" }* n4 M8 S
}
复制代码
bool Subtitles::drawSubtitle(uint32 timestamp, bool force) {
, Z: a ^$ x+ c2 u
Common::String subtitle;
9 `6 T* E J5 i( M
if (_loaded) {
; {; H+ u& Y. i8 |) U& l n, [
subtitle = _srtParser.getSubtitle(timestamp);
+ k" h$ @7 X0 P3 q( D5 r
} else if (_subtitleDev) {
- ~# G( [5 t; F$ U
subtitle = _fname;
; b0 H- X+ W( @+ t" g% d; z6 j
uint32 hours, mins, secs, msecs;
2 S8 G) ~& }5 D: b! S( m2 R
secs = timestamp / 1000;
' [3 {8 Q- { ~! p w. ]; \: b: Q
hours = secs / 3600;
& ^' T5 H2 V T# ^
mins = (secs / 60) % 60;
0 s0 a2 X9 V$ k* T
secs %= 60;
6 x, ~/ I7 w4 o r3 W5 S7 L
msecs = timestamp % 1000;
) @! T5 w- u% Y7 O4 b
subtitle += " " + Common::String::format("%02u:%02u:%02u,%03u", hours, mins, secs, msecs);
4 e9 F" P4 L. r% h9 x
} else {
8 h3 E, y3 L" V+ `! P
return false;
1 J9 D# M2 x9 [7 x3 \1 M4 y
}
) W6 c9 |; l" P9 U v% i4 U
. }( N- j9 x( w. ^
int16 width = g_system->getOverlayWidth(),
8 z6 T# B! U9 C3 b) ]. v) M. F+ T" q
height = g_system->getOverlayHeight();
5 ^3 v' I: f Z _
4 E# J/ H1 s# u* V4 w. t
if (width != _lastOverlayWidth ||
3 g6 E( r. {; S3 u# L
height != _lastOverlayHeight) {
( L, d/ {( k7 A" r$ m7 x; t
_lastOverlayWidth = width;
2 F/ k6 T7 ^5 b! u" {/ j
_lastOverlayHeight = height;
) x) w2 V5 V$ Z1 E
# W$ G# n9 R- Q
// Recalculate the real bounding box to use
3 {/ m. y \/ m+ w2 l" M
_realBBox = _requestedBBox;
/ Z. {8 L4 l3 S) B( Y
; e6 y' j0 y6 E. R S6 U9 p1 ]) x7 B
if (_realBBox.bottom > height) {
" C3 Q5 S9 _9 F" Q4 [( X
// First try to move the bounding box
; f) k1 E M" k/ w, f8 u$ l/ \& }3 C
_realBBox.top -= _realBBox.bottom - height;
% y# T2 g% M! p- k. X' d& P/ i
_realBBox.bottom = height;
+ E) f) W i( O7 T& s( N, y
}
1 N. G6 J" U8 ?' y% ]/ c" m* d
if (_realBBox.top < 0) {
* @+ y; \# W, T( V- P" T. I* Z8 h
// Not enough space
7 I/ w! t7 V, k8 M
_realBBox.top = 0;
( f3 z' Y+ |1 J4 l0 B c8 j
}
9 C9 z- T0 F# x7 r- \$ ?: h1 ^* A
8 b) N- M& h# u" R* t
if (_realBBox.right > width) {
& \' e) E' y# e7 C
// First try to move the bounding box
5 x! |' L5 d9 H6 e; g9 {' P6 G0 G5 X/ E
_realBBox.left -= _realBBox.right - width;
C5 {$ }- a* W5 O1 d4 S0 B
_realBBox.right = width;
# | [( q6 G5 I" n6 B
}
, x+ ^: q0 c8 T' f, W5 m* j5 f1 I
if (_realBBox.left < 0) {
. v/ n5 P" z- a8 p0 Q' b' ^
// Not enough space
+ b0 T3 P* O; S. X( x# L- b
_realBBox.left = 0;
% I1 O& g4 w, e7 @$ A K0 i
}
, ^; S. q* U Z; D w- U. Q3 I
/ i5 O" W: E3 F
force = true;
2 u; O! m. W: T5 s. f9 Q5 I5 P
}
q6 i& x. p* X& J
+ t6 g& L9 h& X1 G
if (!force && _overlayHasAlpha && subtitle == _subtitle)
/ y) U4 [& [1 H+ r; f
return false;
% @' b2 N) O3 L6 J7 r2 u$ R* ?; w+ A
7 u) S, X; S' C
if (force || subtitle != _subtitle) {
/ i* L( Z% Y# G+ r9 |/ `7 E; u( G
debug(1, "%d: %s", timestamp, subtitle.c_str());
- g/ i* [5 |6 g. Z, z
5 g0 t+ s7 [* n2 X
_subtitle = subtitle;
& ^7 _# @2 l& m" D' T
renderSubtitle();
* }3 h/ E* Y4 @7 f
}
/ l, j" `# n3 j4 g
1 @" a2 ^7 |0 [, t# J& `2 v7 D5 K
if (_overlayHasAlpha) {
1 H$ ]5 }) O& [# q0 z3 ~
// When we have alpha, draw the whole surface without thinking it more
9 I# P3 G6 h4 P$ z; q: g' e
g_system->copyRectToOverlay(_surface->getPixels(), _surface->pitch, _realBBox.left, _realBBox.top, _realBBox.width(), _realBBox.height());
& S* g! F. l" ~, W+ ^( M
} else {
4 O: E+ H# y: ?6 h9 h a
// When overlay doesn't have alpha, showing it hides the underlying game screen
% J* ~! G* a7 Z6 D& m
// We force a copy of the game screen to the overlay by clearing it
+ @$ p; J1 y% F3 @5 \ E; X
// We then draw the smallest possible surface to minimize black rectangle behind text
/ e [0 g5 h4 o0 o
g_system->clearOverlay();
# O- }) z: z3 L7 _
g_system->copyRectToOverlay((byte *)_surface->getPixels() + _drawRect.top * _surface->pitch + _drawRect.left * _surface->format.bytesPerPixel, _surface->pitch,
" b% j. Y6 f% @/ }- z
_realBBox.left + _drawRect.left, _realBBox.top + _drawRect.top, _drawRect.width(), _drawRect.height());
6 U, s8 `3 g% o
}
! c [: G2 m1 O4 j2 t
0 {: d) X, F a. x( `, f; s
return true;
& o$ m, i$ c6 n8 d
}
+ {, T; \1 ~" n! t+ q
复制代码
" E, ~, w; I. Y7 V7 a0 I
( K8 W: ]) u- I# H
* N, Z' `- y: B- E( K
/ P8 V; _) g, @. \+ m$ d/ P# ^
t# I& x* P/ K+ l2 Y
0 Z1 j7 h" F. k' V
) J# } s& Z0 H/ x% i# v
欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/)
Powered by Discuz! X3.2