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/overlays.h"
24
25 #include "bladerunner/bladerunner.h"
26 #include "bladerunner/game_constants.h"
27
28 #include "bladerunner/archive.h"
29 #include "bladerunner/savefile.h"
30 #include "bladerunner/vqa_player.h"
31
32 #include "graphics/surface.h"
33
34 namespace BladeRunner {
35
Overlays(BladeRunnerEngine * vm)36 Overlays::Overlays(BladeRunnerEngine *vm) {
37 _vm = vm;
38 }
39
init()40 bool Overlays::init() {
41 reset();
42 _videos.resize(kOverlayVideos);
43
44 for (int i = 0; i < kOverlayVideos; ++i) {
45 _videos[i].vqaPlayer = nullptr;
46 resetSingle(i);
47 }
48
49 return true;
50 }
51
~Overlays()52 Overlays::~Overlays() {
53 for (int i = 0; i < kOverlayVideos; ++i) {
54 resetSingle(i);
55 }
56 _videos.clear();
57 reset();
58 }
59
play(const Common::String & name,int loopId,bool loopForever,bool startNow,int a6)60 int Overlays::play(const Common::String &name, int loopId, bool loopForever, bool startNow, int a6) {
61 assert(name.size() <= 12);
62 if (loopId < 0) {
63 warning("Overlays::play - loop id can't be a negative number!");
64 return -1;
65 }
66
67 int32 hash = MIXArchive::getHash(name);
68 int index = findByHash(hash);
69 if (index < 0) {
70 index = findEmpty();
71 if (index < 0) {
72 return index;
73 }
74 _videos[index].loaded = true;
75 _videos[index].name = name;
76 _videos[index].hash = hash;
77 _videos[index].loopId = loopId;
78 _videos[index].enqueuedLoopId = -1;
79 _videos[index].loopForever = loopForever;
80 _videos[index].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront, Common::String::format("%s.VQA", name.c_str()));
81
82 if (!_videos[index].vqaPlayer) {
83 resetSingle(index);
84 return -1;
85 }
86 // TODO? Removed as redundant
87 // repeat forever
88 //_videos[index].vqaPlayer->setBeginAndEndFrame(0, 0, -1, kLoopSetModeJustStart, nullptr, nullptr);
89 }
90
91 bool skipNewVQAPlayerOpen = false;
92 if (_videos[index].vqaPlayer
93 && !startNow
94 && _videos[index].vqaPlayer->getFrameCount() > 0
95 ) {
96 skipNewVQAPlayerOpen = true;
97 _videos[index].enqueuedLoopId = loopId;
98 }
99
100 if (skipNewVQAPlayerOpen || _videos[index].vqaPlayer->open()) {
101 _videos[index].vqaPlayer->setLoop(
102 loopId,
103 loopForever ? -1 : 0,
104 startNow ? kLoopSetModeImmediate : kLoopSetModeEnqueue,
105 nullptr, nullptr);
106 } else {
107 resetSingle(index);
108 return -1;
109 }
110 return index;
111 }
112
resume(bool isLoadingGame)113 void Overlays::resume(bool isLoadingGame) {
114
115 for (int i = 0; i < kOverlayVideos; ++i) {
116 if (_videos[i].loaded && isLoadingGame) {
117 _videos[i].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront, Common::String::format("%s.VQA", _videos[i].name.c_str()));
118 if (!_videos[i].vqaPlayer) {
119 resetSingle(i);
120 continue;
121 }
122
123 _videos[i].vqaPlayer->open();
124 _videos[i].vqaPlayer->setLoop(
125 _videos[i].loopId,
126 _videos[i].loopForever ? -1 : 0,
127 kLoopSetModeImmediate,
128 nullptr, nullptr);
129
130 _videos[i].vqaPlayer->seekToFrame(_videos[i].frame);
131 _videos[i].vqaPlayer->update(true);
132 }
133 }
134 }
135
remove(const Common::String & name)136 void Overlays::remove(const Common::String &name) {
137 int index = findByHash(MIXArchive::getHash(name));
138 if (index >= 0) {
139 resetSingle(index);
140 }
141 }
142
removeAll()143 void Overlays::removeAll() {
144 for (int i = 0; i < kOverlayVideos; ++i) {
145 if (_videos[i].loaded) {
146 resetSingle(i);
147 }
148 }
149 }
150
tick()151 void Overlays::tick() {
152 for (int i = 0; i < kOverlayVideos; ++i) {
153 if (_videos[i].loaded) {
154 _videos[i].frame = _videos[i].vqaPlayer->update(true);
155 if (_videos[i].frame < 0) {
156 resetSingle(i);
157 }
158 }
159 }
160 }
161
findByHash(int32 hash) const162 int Overlays::findByHash(int32 hash) const {
163 for (int i = 0; i < kOverlayVideos; ++i) {
164 if (_videos[i].loaded && _videos[i].hash == hash) {
165 return i;
166 }
167 }
168 return -1;
169 }
170
findEmpty() const171 int Overlays::findEmpty() const {
172 for (int i = 0; i < kOverlayVideos; ++i) {
173 if (!_videos[i].loaded) {
174 return i;
175 }
176 }
177 return -1;
178 }
179
resetSingle(int i)180 void Overlays::resetSingle(int i) {
181 assert(i >= 0 && i < (int)_videos.size());
182 if (_videos[i].vqaPlayer) {
183 delete _videos[i].vqaPlayer;
184 _videos[i].vqaPlayer = nullptr;
185 }
186 _videos[i].loaded = false;
187 _videos[i].hash = 0;
188 _videos[i].frame = -1;
189 _videos[i].name.clear();
190 }
191
reset()192 void Overlays::reset() {
193 _videos.clear();
194 }
195
save(SaveFileWriteStream & f)196 void Overlays::save(SaveFileWriteStream &f) {
197 for (int i = 0; i < kOverlayVideos; ++i) {
198 // 37 bytes per overlay
199 Video &ov = _videos[i];
200
201 f.writeBool(ov.loaded);
202 f.writeInt(0); // vqaPlayer pointer
203 f.writeStringSz(ov.name, 13);
204 f.writeSint32LE(ov.hash);
205 if (ov.enqueuedLoopId != -1) {
206 // When there is an enqueued video, save that loop Id instead
207 f.writeInt(ov.enqueuedLoopId);
208 } else {
209 f.writeInt(ov.loopId);
210 }
211 f.writeBool(ov.loopForever);
212 f.writeInt(ov.frame);
213 }
214 }
215
load(SaveFileReadStream & f)216 void Overlays::load(SaveFileReadStream &f) {
217 for (int i = 0; i < kOverlayVideos; ++i) {
218 // 37 bytes per overlay
219 Video &ov = _videos[i];
220
221 ov.loaded = f.readBool();
222 f.skip(4); // vqaPlayer pointer
223 ov.vqaPlayer = nullptr;
224 ov.name = f.readStringSz(13);
225 ov.hash = f.readSint32LE();
226 ov.loopId = f.readInt();
227 ov.loopForever = f.readBool();
228 ov.frame = f.readInt();
229 }
230 }
231
232 } // End of namespace BladeRunner
233