冒险解谜游戏中文网 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 编辑
# C% k# c1 H: M% z: t* D
$ \4 t, h7 @$ V. \) t$ Z- v
这个游戏原本是没有字幕的,但是在Scummvm论坛上发现了一个帖子,
2 f) Z c' z! }; i6 R0 ?
讨论的内容是关于在原本没有字幕的游戏上加上字幕。(最初的缘由,是为了帮助一位失聪的朋友)
) }9 \2 h; _2 `: b1 J
https://forums.scummvm.org/viewtopic.php?t=7168
5 W3 `. {5 H3 Y" s6 n8 c
[Scummvm-devel] Displaying subtitles in voice-only games (narkive.com)
! C& X2 @# f- r* h
) ^) g) C& h; _8 [. x4 A
前段时间第七访客出了25周年纪念版(The 7th Guest 25th Anniversary Edition。
) p% _1 e. ?# T7 |* b2 p, |
在这个版本中,游戏的视频是有字幕的,因此把这个视频的字幕用到Scummvm中就成为了可能。
7 C( c1 R! V6 _) X
9 V& j$ Y$ V8 v' R
我查看了一下最新版本的Scummvm的代码,发现老外已经加入了一部分代码。
r. d3 e4 E- A& {) l/ m
在此基础上,汉化是大有希望的。此种汉化方法,也是前所未有的,如果真的实现了将会有重要意义。
2 ~& R" L2 z+ ~/ H% J
) p& `) W8 p9 r! f, l! V0 u o) o
类似游戏还有
· Groovie
" o* J! T8 r* E! `, H2 t. o
- The 7th Guest
6 c) p* ^& t6 M- V( G. W8 R4 E0 \
- The 11th Hour
0 j7 P& \ b) _- |
# d8 n# L- e4 `. b
· MADE
0 S2 q2 X% k* l3 K
- Return to Zork (descriptions are text only, while spoken dialogs lack
7 b, ]# G0 \3 K) \9 o3 w2 \& R9 f# ]
any text)
4 c, G* H3 _$ v7 ]1 [
# D6 |1 x! g* z% a6 p; C4 l& M
· SCI 1
# J0 D* b6 I$ q" u6 j# ]2 m
- King's Quest V (CD Version). In this case, just enabling voice and text
7 P# b' v0 z8 A, W1 Q
simultanously would allow a 3rd party to create a set of MSG files
6 e! C% c( j& B F7 S* p6 T8 N) i
containing the voice transcription/translation, as it happened with Gabriel
+ I: h; ]- o) w, m7 C
Knight II.
4 T4 J. B$ E, T5 Q9 B' V( R
+ P& e8 i$ d1 P8 @0 N
& r! q9 q6 A; c/ F( i7 U5 ], U
Future engines:
8 ]; J7 c/ b0 ~1 y' i
o: @1 ~7 J& o. J) d y
· SCI 21
' d7 @' h5 Z* Y
- Gabriel Knight II: The Beast Within (Already a fan patch available in
" a' A# E7 z+ B
order to enable the text display feature)
% X0 }' t. `) m9 C. A6 l% w, l
- Phantasmagoria
. l7 K2 Z* _3 T: I% S0 j; n- z
- Rama
( X* O# A# _9 Q/ C: {- A
- Shivers
/ u: x; W4 o7 d% x
- Phantasmagoria II: A Puzzle Of Flesh
! [3 L+ B7 l9 O7 K4 H, M
% p. H: Z2 y$ B# i, b7 }0 E! j
· SCI 3
3 L: w8 e* {$ Q( [4 E( F
- Lighthouse: The Dark Being
7 Q6 p, k2 F# V* ~) h
- k6 n' I% c; X* D: h
· M4/MADS
; ?, u L: O0 W& u& S
- Orion Burger
6 V, T( k' ~% d& E& s% p
( h$ Z. L" o7 Y I
· Mohawk
" q7 M8 [* v6 w* X3 c
- Myst
- s3 n# z: _9 z, @5 n- v3 E
- Riven: The Sequel to Myst
复制代码
0 o% {7 p' L" p! e8 x! ~
& T+ ^% C5 N. ?# v
5 c5 i* b: x* A8 v
7 H, a( q4 {" c1 T5 z
相关代码如下
- R; x" _: I! D6 b9 V, d
bool VideoPlayer::playFrame() {
; l* L% M% P6 \5 L) `0 c
bool end = true;
( T L, n7 S1 f7 X! ~; z
! T5 P G" P7 h0 Q% O) D9 s
// Process the next frame while the file is open
; L) I1 R( a4 ?' ], z
if (_file) {
9 {1 p0 y- ]5 u4 }* q
end = playFrameInternal();
3 d4 R% M2 h* J$ U9 V! r
( i$ G( E. C" T& H! x- ]" _
_subtitles.drawSubtitle(_lastFrameTime - _startTime);
6 F8 `' U4 X: ^1 o- [. s2 a/ W
}
复制代码
bool Subtitles::drawSubtitle(uint32 timestamp, bool force) {
/ R" j& P% X8 p6 e. A" A
Common::String subtitle;
" I( ]5 A8 L7 M! T$ a
if (_loaded) {
, q$ F! d }) r" k% h* k& W5 I
subtitle = _srtParser.getSubtitle(timestamp);
% Q2 T' |6 q! @3 h( _! K$ ^" `
} else if (_subtitleDev) {
" o$ X" C c8 }9 l
subtitle = _fname;
4 E0 Q" L4 O2 N6 h+ O. u+ j+ h
uint32 hours, mins, secs, msecs;
6 L h( e l6 x7 `
secs = timestamp / 1000;
* c8 o$ C x# ]
hours = secs / 3600;
5 E7 P7 E2 M4 k
mins = (secs / 60) % 60;
3 A" \/ G, e+ }7 ^( o7 w: H
secs %= 60;
c4 J2 p6 \* F; t+ Y
msecs = timestamp % 1000;
' ~- ~) F2 g. w) y) Q( q' e) T
subtitle += " " + Common::String::format("%02u:%02u:%02u,%03u", hours, mins, secs, msecs);
& T- w1 ?( Z. J2 o$ \, x% u
} else {
5 {/ _# Q+ L* k8 j% g) ~
return false;
" [7 Z1 F% D( [) F+ Q6 B1 C; l: G
}
3 }; p" G/ Y" W% C9 E" X
3 v" R. {# p; G" W$ l% ]5 _
int16 width = g_system->getOverlayWidth(),
/ b' y0 P7 G- l+ X7 S; Z
height = g_system->getOverlayHeight();
( |* V5 X1 \, X1 C; C( |1 U
* @* X J' A' I% _' P4 b0 F8 D1 ^
if (width != _lastOverlayWidth ||
( d( \$ Q: C# F8 }: k: b
height != _lastOverlayHeight) {
# U1 x ?1 L7 I) M! G0 |' m
_lastOverlayWidth = width;
2 P6 A; F. s6 [, [; {" Y7 _, d
_lastOverlayHeight = height;
6 D* ]0 A) N* S, a
: `% M4 T4 D# q, m
// Recalculate the real bounding box to use
8 |& C# N& s" O7 h* k
_realBBox = _requestedBBox;
- x, V# a. h* P" Z- ~; z
4 s: ]% [( C9 f: i
if (_realBBox.bottom > height) {
8 O/ a' X8 k' j" u- M
// First try to move the bounding box
3 V( L2 N9 [5 G7 N7 Y# x7 f
_realBBox.top -= _realBBox.bottom - height;
1 V, d' B# o" O
_realBBox.bottom = height;
# k( f4 c4 W% \; t2 @& N
}
+ @2 o X4 w/ |3 E
if (_realBBox.top < 0) {
* i9 T" q g: y; R- G& ^
// Not enough space
, K. V- \9 O4 |, l$ ]' J
_realBBox.top = 0;
4 E: v5 ?: a" v- p6 j
}
: v1 F7 a( f/ v& K3 r( g/ V' H
q* s( C5 d2 s
if (_realBBox.right > width) {
9 F v6 v" u, G3 S! g
// First try to move the bounding box
* q" v9 {9 `5 U, p' H
_realBBox.left -= _realBBox.right - width;
. p. {8 I8 s- x
_realBBox.right = width;
R5 F! A4 g5 n( w# [, c
}
2 i$ u$ Z U" V7 g9 G1 i; v
if (_realBBox.left < 0) {
$ Q9 y h* V" ~1 o& V" U& ^
// Not enough space
6 V8 q3 O, B5 l) `. Y& {4 k
_realBBox.left = 0;
6 |) G5 E; q2 W% ~' {4 E; i
}
3 X4 d9 O# P& l! p$ @
2 o/ s' Z# u, M% O
force = true;
& X: }+ b0 J; i# \( ~: {
}
6 P4 a `7 \- F' `$ l+ w% ?
6 s5 w- n/ z* r) R5 _; A2 l
if (!force && _overlayHasAlpha && subtitle == _subtitle)
# x) l, S0 n) p/ a' A" z
return false;
/ g; @8 l2 g: \) r2 m. Y' R
; x. \: L9 M$ A8 _
if (force || subtitle != _subtitle) {
# A: O8 v/ ~! T9 P6 {3 }) g; j3 t
debug(1, "%d: %s", timestamp, subtitle.c_str());
% W" m1 r- F5 p0 S
& w/ `! c' J1 S1 M3 M
_subtitle = subtitle;
W4 f2 Y# O0 B" \! @/ g5 h
renderSubtitle();
! b/ ^8 i/ \6 S. l5 S7 R. d) ^# A
}
' k, r B2 I4 ?7 k) u/ g- S2 C
4 G0 `- A5 T. H3 q; {4 k4 a1 i
if (_overlayHasAlpha) {
0 O1 L. v3 O7 h3 r
// When we have alpha, draw the whole surface without thinking it more
: m! d) l/ k9 U0 K
g_system->copyRectToOverlay(_surface->getPixels(), _surface->pitch, _realBBox.left, _realBBox.top, _realBBox.width(), _realBBox.height());
: I5 v! X Z2 B, |' V
} else {
$ [) G6 m7 I" \, s' `) b% s$ _: [, r
// When overlay doesn't have alpha, showing it hides the underlying game screen
' X3 u$ L5 C% a4 ?9 T$ |( K
// We force a copy of the game screen to the overlay by clearing it
) s# G. ^( j% w2 e4 {: t
// We then draw the smallest possible surface to minimize black rectangle behind text
3 R0 T+ q( J% H
g_system->clearOverlay();
& i! C% b! N! w) d2 l
g_system->copyRectToOverlay((byte *)_surface->getPixels() + _drawRect.top * _surface->pitch + _drawRect.left * _surface->format.bytesPerPixel, _surface->pitch,
" K* d7 D4 k/ s( _3 P( l
_realBBox.left + _drawRect.left, _realBBox.top + _drawRect.top, _drawRect.width(), _drawRect.height());
0 b' z( W; t! @: u) B# l/ s
}
) B' _! N8 i v7 o" x) C; J2 I. _
1 Z4 q4 j5 }7 R% M1 Q- e
return true;
1 v! T& k3 p R$ N7 l8 J
}
0 q# s4 B7 e9 F5 p" X' y# n3 X+ A
复制代码
2 J3 @3 D$ r5 u: `
6 t& _' ]3 J; e, w5 n4 z& k
, @- d: w9 A. M0 N
. T3 ?- {# \2 t2 c d) M1 g2 `+ F
/ g1 Z: T7 L; Z, M* c2 A5 R0 X* v( o
8 G0 Z$ U5 d; e5 a Q0 Z% ]
: S& ~$ P" t u+ G$ I2 \
欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://www.chinaavg.com/)
Powered by Discuz! X3.2