1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "bladerunner/outtake.h"
24 
25 #include "bladerunner/bladerunner.h"
26 #include "bladerunner/chapters.h"
27 #include "bladerunner/subtitles.h"
28 #include "bladerunner/vqa_player.h"
29 #include "bladerunner/time.h"
30 #include "bladerunner/ambient_sounds.h"
31 #include "bladerunner/audio_player.h"
32 #include "bladerunner/game_constants.h"
33 #include "bladerunner/game_info.h"
34 
35 #include "common/debug.h"
36 #include "common/events.h"
37 #include "common/system.h"
38 
39 namespace BladeRunner {
40 
OuttakePlayer(BladeRunnerEngine * vm)41 OuttakePlayer::OuttakePlayer(BladeRunnerEngine *vm) {
42 	_vm = vm;
43 	_surfaceVideo.create(_vm->_surfaceBack.w, _vm->_surfaceBack.h, _vm->_surfaceBack.format);
44 }
45 
~OuttakePlayer()46 OuttakePlayer::~OuttakePlayer() {
47 	_surfaceVideo.free();
48 }
49 
play(const Common::String & name,bool noLocalization,int container)50 void OuttakePlayer::play(const Common::String &name, bool noLocalization, int container) {
51 	Common::String oldOuttakeFile = Common::String::format("OUTTAKE%d.MIX", _vm->_chapters->currentResourceId());
52 	Common::String newOuttakeFile = Common::String::format("OUTTAKE%d.MIX", container);
53 
54 	if (container > 0) {
55 		if (_vm->isArchiveOpen(oldOuttakeFile)) {
56 			_vm->closeArchive(oldOuttakeFile);
57 		}
58 
59 		_vm->openArchive(newOuttakeFile);
60 	}
61 
62 	_vm->playerLosesControl();
63 
64 	Common::String resName = name;
65 	if (!noLocalization) {
66 		resName = resName + "_" + _vm->_languageCode;
67 	}
68 	Common::String resNameNoVQASuffix = resName;
69 	resName = resName + ".VQA";
70 
71 	VQAPlayer vqaPlayer(_vm, &_surfaceVideo, resName); // in original game _surfaceFront is used here, but for proper subtitles rendering we need separate surface
72 	vqaPlayer.open();
73 
74 	_vm->_vqaIsPlaying = true;
75 	_vm->_vqaStopIsRequested = false;
76 
77 	while (!_vm->_vqaStopIsRequested && !_vm->shouldQuit()) {
78 		_vm->handleEvents();
79 
80 		if (!_vm->_windowIsActive) {
81 			continue;
82 		}
83 
84 		int frame = vqaPlayer.update();
85 		blit(_surfaceVideo, _vm->_surfaceFront); // This helps to make subtitles disappear properly, if the video is rendered in separate surface and then pushed to the front surface
86 		if (frame == -3) { // end of video
87 			if (_vm->_cutContent && resName.equals("FLYTRU_E.VQA")) {
88 				_vm->_ambientSounds->removeAllNonLoopingSounds(true);
89 				_vm->_ambientSounds->removeAllLoopingSounds(1u);
90 			}
91 			break;
92 		}
93 
94 		if (frame >= 0) {
95 			_vm->_subtitles->loadOuttakeSubsText(resNameNoVQASuffix, frame);
96 			_vm->_subtitles->tickOuttakes(_vm->_surfaceFront);
97 			_vm->blitToScreen(_vm->_surfaceFront);
98 			if (_vm->_cutContent && resName.equals("FLYTRU_E.VQA")) {
99 				// This FLYTRU_E outtake has 150 frames
100 				//
101 				// We can have at most kLoopingSounds (3) looping ambient tracks
102 				// Outtakes in general use a specific Mixer Sound Type (ie. VQAPlayer::kVQASoundType)
103 				//      so the sounds here should conform too.
104 				//     (see VQAPlayer::update())
105 				//
106 				// No need for _ambientSounds->tick() since it's not required for looping ambient tracks,
107 				// nor for explicitly played Sounds (via playSound())
108 				// It is harmless however, so it could remain.
109 				//_vm->_ambientSounds->tick();
110 				switch (frame) {
111 				case 0:
112 					_vm->_ambientSounds->addLoopingSound(kSfxLABAMB1,   95, 0, 0u, VQAPlayer::kVQASoundType);
113 					_vm->_ambientSounds->addLoopingSound(kSfxROOFAIR1, 100, 0, 0u, VQAPlayer::kVQASoundType);
114 					_vm->_ambientSounds->addLoopingSound(kSfxPSPA6,     74, 0, 1u, VQAPlayer::kVQASoundType);
115 					break;
116 				case 18:
117 					_vm->_ambientSounds->playSound(kSfxSPIN2A, 100, 90, 20, 99, VQAPlayer::kVQASoundType);
118 					break;
119 				case 24:
120 					_vm->_ambientSounds->playSound(kSfxSWEEP4, 45, 90, 20, 99, VQAPlayer::kVQASoundType);
121 					break;
122 				case 32:
123 					if (_vm->_rnd.getRandomNumberRng(1, 5) < 4)
124 						_vm->_ambientSounds->playSound(kSfxTHNDER3, 82, -20, -20, 99, VQAPlayer::kVQASoundType);
125 					break;
126 				case 41:
127 					_vm->_ambientSounds->playSound(kSfxMUSVOL8, 22, 46, 46, 99, VQAPlayer::kVQASoundType);
128 					break;
129 				case 52:
130 					if (_vm->_rnd.getRandomNumberRng(1, 4) < 4)
131 						_vm->_ambientSounds->playSound(kSfxTHNDR3, 90, 10, 10, 89, VQAPlayer::kVQASoundType);
132 					break;
133 				case 78:
134 					if (_vm->_rnd.getRandomNumberRng(1, 5) < 5)
135 						_vm->_ambientSounds->playSound(kSfxSIREN2, 62, -60, 45, 99, VQAPlayer::kVQASoundType);
136 					break;
137 				case 105:
138 					_vm->_ambientSounds->playSound(kSfxSWEEP3, 22, 20, 95, 99, VQAPlayer::kVQASoundType);
139 					break;
140 				case 112:
141 					if (_vm->_rnd.getRandomNumberRng(1, 5) < 4)
142 						_vm->_ambientSounds->playSound(kSfxTHNDER4, 95, -20, -20, 99, VQAPlayer::kVQASoundType);
143 					break;
144 				}
145 			}
146 		}
147 	}
148 
149 	if ((_vm->_vqaStopIsRequested || _vm->shouldQuit())
150 		&& _vm->_cutContent && resName.equals("FLYTRU_E.VQA")) {
151 		_vm->_ambientSounds->removeAllNonLoopingSounds(true);
152 		_vm->_ambientSounds->removeAllLoopingSounds(0u);
153 		_vm->_audioPlayer->stopAll();
154 	}
155 
156 	_vm->_vqaIsPlaying = false;
157 	_vm->_vqaStopIsRequested = false;
158 	vqaPlayer.close();
159 
160 	_vm->playerGainsControl();
161 
162 	if (container > 0) {
163 		if (_vm->isArchiveOpen(newOuttakeFile)) {
164 			_vm->closeArchive(newOuttakeFile);
165 		}
166 
167 		_vm->openArchive(oldOuttakeFile);
168 	}
169 }
170 
171 } // End of namespace BladeRunner
172