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 "audio/audiostream.h"
24 #include "audio/decoders/raw.h"
25 #include "common/config-manager.h"
26 #include "common/memstream.h"
27 #include "common/savefile.h"
28 #include "common/serializer.h"
29 #include "common/system.h"
30 #include "common/zlib.h"
31 #include "graphics/palette.h"
32
33 #include "composer/composer.h"
34 #include "composer/graphics.h"
35
36 namespace Composer {
37
38 template<class T>
syncArray(Common::Serializer & ser,Common::Array<T> & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)39 void ComposerEngine::syncArray(Common::Serializer &ser, Common::Array<T> &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
40 if (ser.isSaving()) {
41 uint32 size = data.size();
42 ser.syncAsUint32LE(size, minVersion, maxVersion);
43 for (typename Common::Array<T>::iterator i = data.begin(); i != data.end(); i++) {
44 sync<T>(ser, *i, minVersion, maxVersion);
45 }
46 } else {
47 uint32 size;
48 data.clear();
49 ser.syncAsUint32LE(size, minVersion, maxVersion);
50 for (uint32 i = 0; i < size; i++) {
51 T item;
52 sync<T>(ser, item, minVersion, maxVersion);
53 data.push_back(item);
54 }
55 }
56 }
57 template<class T>
syncList(Common::Serializer & ser,Common::List<T> & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)58 void ComposerEngine::syncList(Common::Serializer &ser, Common::List<T> &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
59 if (ser.isSaving()) {
60 uint32 size = data.size();
61 ser.syncAsUint32LE(size, minVersion, maxVersion);
62 for (typename Common::List<T>::iterator i = data.begin(); i != data.end(); i++) {
63 sync<T>(ser, *i, minVersion, maxVersion);
64 }
65 } else {
66 uint32 size;
67 data.clear();
68 ser.syncAsUint32LE(size, minVersion, maxVersion);
69 for (uint32 i = 0; i < size; i++) {
70 T item;
71 sync<T>(ser, item, minVersion, maxVersion);
72 data.push_back(item);
73 }
74 }
75 }
76 template<class T>
syncListReverse(Common::Serializer & ser,Common::List<T> & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)77 void ComposerEngine::syncListReverse(Common::Serializer &ser, Common::List<T> &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
78 if (ser.isSaving()) {
79 uint32 size = data.size();
80 ser.syncAsUint32LE(size, minVersion, maxVersion);
81 for (typename Common::List<T>::iterator i = data.reverse_begin(); i != data.end(); i--) {
82 sync<T>(ser, *i, minVersion, maxVersion);
83 }
84 } else {
85 uint32 size;
86 data.clear();
87 ser.syncAsUint32LE(size, minVersion, maxVersion);
88 for (uint32 i = 0; i < size; i++) {
89 T item;
90 sync<T>(ser, item, minVersion, maxVersion);
91 data.push_front(item);
92 }
93 }
94 }
95 template<>
sync(Common::Serializer & ser,uint16 & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)96 void ComposerEngine::sync<uint16>(Common::Serializer &ser, uint16 &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
97 ser.syncAsUint16LE(data, minVersion, maxVersion);
98 }
99 template<>
sync(Common::Serializer & ser,uint32 & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)100 void ComposerEngine::sync<uint32>(Common::Serializer &ser, uint32 &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
101 ser.syncAsUint32LE(data, minVersion, maxVersion);
102 }
103 template<>
sync(Common::Serializer & ser,Library & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)104 void ComposerEngine::sync<Library>(Common::Serializer &ser, Library &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
105 if (ser.isSaving()) {
106 ser.syncAsUint16LE(data._id, minVersion, maxVersion);
107 ser.syncString(data._group, minVersion, maxVersion);
108 } else {
109 uint16 id;
110 ser.syncAsUint16LE(id, minVersion, maxVersion);
111 ser.syncString(_bookGroup, minVersion, maxVersion);
112 loadLibrary(id);
113 }
114 }
115 template<>
syncListReverse(Common::Serializer & ser,Common::List<Library> & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)116 void ComposerEngine::syncListReverse<Library>(Common::Serializer &ser, Common::List<Library> &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
117 if (ser.isSaving()) {
118 uint32 size = data.size();
119 ser.syncAsUint32LE(size, minVersion, maxVersion);
120 for (Common::List<Library>::iterator i = data.reverse_begin(); i != data.end(); i--) {
121 sync<Library>(ser, *i, minVersion, maxVersion);
122 }
123 } else {
124 uint32 size;
125 ser.syncAsUint32LE(size, minVersion, maxVersion);
126 for (uint32 i = 0; i < size; i++) {
127 Library item;
128 sync<Library>(ser, item, minVersion, maxVersion);
129 }
130 }
131 }
132 template<>
sync(Common::Serializer & ser,PendingPageChange & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)133 void ComposerEngine::sync<PendingPageChange>(Common::Serializer &ser, PendingPageChange &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
134 ser.syncAsUint16LE(data._pageId, minVersion, maxVersion);
135 ser.syncAsByte(data._remove, minVersion, maxVersion);
136 }
137 template<>
sync(Common::Serializer & ser,OldScript * & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)138 void ComposerEngine::sync<OldScript *>(Common::Serializer &ser, OldScript *&data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
139 uint16 id;
140 uint32 pos, delay;
141 if (ser.isSaving()) {
142 pos = data->_stream->pos();
143 id = data->_id;
144 delay = data->_currDelay;
145 }
146 ser.syncAsUint32LE(pos);
147 ser.syncAsUint16LE(id);
148 ser.syncAsUint32LE(delay);
149 if (ser.isLoading()) {
150 data = new OldScript(id, getResource(ID_SCRP, id));
151 data->_currDelay = delay;
152 data->_stream->seek(pos, SEEK_SET);
153 }
154 }
155 template<>
sync(Common::Serializer & ser,QueuedScript & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)156 void ComposerEngine::sync<QueuedScript>(Common::Serializer &ser, QueuedScript &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
157 ser.syncAsUint32LE(data._baseTime);
158 ser.syncAsUint32LE(data._duration);
159 ser.syncAsUint32LE(data._count);
160 ser.syncAsUint16LE(data._scriptId);
161 if (ser.isLoading()) data._baseTime += _timeDelta;
162 }
163 template<>
sync(Common::Serializer & ser,Pipe * & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)164 void ComposerEngine::sync<Pipe *>(Common::Serializer &ser, Pipe *&data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
165 uint16 id;
166 uint32 offset, tmp;
167 if (ser.isSaving()) {
168 id = data->getPipeId();
169 offset = data->getOffset();
170 tmp = data->_bufferedResources.size();
171 }
172 ser.syncAsUint16LE(id);
173 ser.syncAsUint32LE(offset);
174
175 if (ser.isLoading()) {
176 // On load, get and initialize streams
177 Common::SeekableReadStream *stream;
178 if (getGameType() == GType_ComposerV1) {
179 stream = getResource(ID_PIPE, id);
180 data = new OldPipe(stream, id);
181 } else {
182 stream = getResource(ID_ANIM, id);
183 data = new Pipe(stream, id);
184 }
185 _pipeStreams.push_back(stream);
186 data->setOffset(offset);
187 ser.syncAsUint32LE(tmp);
188 for (uint32 j = tmp; j > 0; j--) {
189 uint32 tag;
190 ser.syncAsUint32LE(tag);
191 ser.syncAsUint32LE(tmp);
192 for (uint32 k = tmp; k > 0; k--) {
193 ser.syncAsUint16LE(id);
194 if (data->hasResource(tag, id))
195 data->getResource(tag, id, true);
196 }
197 }
198 } else {
199 ser.syncAsUint32LE(tmp);
200 for (Pipe::DelMap::iterator i = data->_bufferedResources.begin(); i != data->_bufferedResources.end(); i++) {
201 uint32 key = (*i)._key;
202 ser.syncAsUint32LE(key);
203 syncList<uint16>(ser, (*i)._value, minVersion, maxVersion);
204 }
205 }
206 }
207 template<>
sync(Common::Serializer & ser,AnimationEntry & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)208 void ComposerEngine::sync<AnimationEntry>(Common::Serializer &ser, AnimationEntry &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
209 ser.syncAsUint32LE(data.state);
210 ser.syncAsUint16LE(data.counter);
211 ser.syncAsUint16LE(data.prevValue);
212 }
213 template<>
sync(Common::Serializer & ser,Animation * & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)214 void ComposerEngine::sync<Animation *>(Common::Serializer &ser, Animation *&data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
215 uint16 animId, x, y;
216 uint32 offset, state, param;
217 int32 size;
218 if (ser.isSaving()) {
219 animId = data->_id;
220 offset = data->_offset;
221 x = data->_basePos.x;
222 y = data->_basePos.x;
223 state = data->_state;
224 param = data->_eventParam;
225 size = data->_size;
226 }
227 ser.syncAsUint16LE(animId);
228 ser.syncAsUint32LE(offset);
229 ser.syncAsUint16LE(x);
230 ser.syncAsUint16LE(y);
231 ser.syncAsUint32LE(state);
232 ser.syncAsUint32LE(param);
233 ser.syncAsUint32LE(size);
234 if (ser.isLoading()) {
235 // On load, get and initialize streams
236 loadAnimation(data, animId, x, y, param, size);
237 data->_offset = offset;
238 data->_state = state;
239 uint32 tmp;
240 ser.syncAsUint32LE(tmp);
241 for (uint32 i = 0; i < tmp; i++) {
242 sync<AnimationEntry>(ser, data->_entries[i], minVersion, maxVersion);
243 }
244 } else {
245 syncArray<AnimationEntry>(ser, data->_entries, minVersion, maxVersion);
246 }
247 }
248 template<>
sync(Common::Serializer & ser,Sprite & data,Common::Serializer::Version minVersion,Common::Serializer::Version maxVersion)249 void ComposerEngine::sync<Sprite>(Common::Serializer &ser, Sprite &data, Common::Serializer::Version minVersion, Common::Serializer::Version maxVersion) {
250 ser.syncAsUint16LE(data._id);
251 ser.syncAsUint16LE(data._animId);
252 ser.syncAsSint16LE(data._pos.x);
253 ser.syncAsSint16LE(data._pos.y);
254 ser.syncAsUint16LE(data._surface.w);
255 ser.syncAsUint16LE(data._surface.h);
256 ser.syncAsUint16LE(data._surface.pitch);
257 ser.syncAsUint16LE(data._zorder);
258 if (ser.isLoading())
259 data._surface.setPixels(malloc(data._surface.h * data._surface.pitch));
260 byte *pix = static_cast<byte *>(data._surface.getPixels());
261 for (uint16 y = 0; y < data._surface.h; y++) {
262 for (uint16 x = 0; x < data._surface.w; x++) {
263 ser.syncAsByte(pix[x]);
264 }
265 pix += data._surface.pitch;
266 }
267
268 }
269
getSaveStateName(int slot) const270 Common::String ComposerEngine::getSaveStateName(int slot) const {
271 return Common::String::format("%s.%02d", _targetName.c_str(), slot);
272 }
273
loadGameState(int slot)274 Common::Error ComposerEngine::loadGameState(int slot) {
275 Common::String filename = getSaveStateName(slot);
276 Common::InSaveFile *in;
277 if (!(in = _saveFileMan->openForLoading(filename)))
278 return Common::kPathNotFile;
279
280 Common::Serializer ser(in, NULL);
281 byte magic[4];
282 ser.syncBytes(magic, 4);
283 if (magic[0] != 'C' || magic[1] != 'M' || magic[2] != 'P' || magic[3] != 'S')
284 return Common::kUnknownError;
285
286 ser.syncVersion(0);
287 Common::String desc;
288 ser.syncString(desc);
289 uint32 tmp;
290 ser.syncAsUint32LE(tmp);
291 _rnd->setSeed(tmp);
292 ser.syncAsUint32LE(_currentTime);
293 _timeDelta = _system->getMillis() - _currentTime;
294 _currentTime += _timeDelta;
295 ser.syncAsUint32LE(_lastTime);
296 _lastTime += _timeDelta;
297
298 // Unload all Libraries
299 Common::Array<uint16> libIds;
300 for (Common::List<Library>::iterator i = _libraries.begin(); i != _libraries.end(); i++)
301 libIds.push_back((*i)._id);
302 for (uint32 i = 0; i < libIds.size(); i++)
303 unloadLibrary(libIds[i]);
304
305 syncListReverse<Library>(ser, _libraries);
306 ser.syncString(_bookGroup);
307
308 syncArray<PendingPageChange>(ser, _pendingPageChanges);
309 syncArray<uint16>(ser, _stack);
310 syncArray<uint16>(ser, _vars);
311
312 // Free outdated pointers
313 for (Common::List<OldScript *>::iterator i = _oldScripts.begin(); i != _oldScripts.end(); i++) {
314 delete *i;
315 }
316
317 syncList<OldScript *>(ser, _oldScripts);
318 syncArray<QueuedScript>(ser, _queuedScripts);
319
320 ser.syncAsSint16LE(_lastMousePos.x);
321 ser.syncAsSint16LE(_lastMousePos.y);
322 g_system->warpMouse(_lastMousePos.x, _lastMousePos.y);
323 ser.syncAsByte(_mouseEnabled);
324 ser.syncAsByte(_mouseVisible);
325 ser.syncAsUint16LE(_mouseSpriteId);
326
327 // Free outdated pointers
328 for (Common::List<Pipe *>::iterator i = _pipes.begin(); i != _pipes.end(); i++) {
329 delete *i;
330 }
331 for (Common::Array<Common::SeekableReadStream *>::iterator i = _pipeStreams.begin(); i != _pipeStreams.end(); i++) {
332 delete *i;
333 }
334
335 _pipeStreams.clear();
336 syncListReverse<Pipe *>(ser, _pipes);
337
338 // Free outdated pointers
339 for (Common::List<Animation *>::iterator i = _anims.begin(); i != _anims.end(); i++) {
340 delete *i;
341 }
342
343 syncList<Animation *>(ser, _anims);
344 syncList<Sprite>(ser, _sprites);
345
346 _dirtyRects.clear();
347
348 // Redraw the whole screen
349 _dirtyRects.push_back(Common::Rect(0, 0, 640, 480));
350 byte palbuf[256 * 3];
351 ser.syncBytes(palbuf, 256 * 3);
352 _system->getPaletteManager()->setPalette(palbuf, 0, 256);
353 _needsUpdate = true;
354
355 _mixer->stopAll();
356 _audioStream = NULL;
357
358 // Restore the buffered audio
359 ser.syncAsSint16LE(_currSoundPriority);
360 int32 numSamples;
361 ser.syncAsSint32LE(numSamples);
362 int16 *audioBuffer = (int16 *)malloc(numSamples * 2);
363 for (int32 i = 0; i < numSamples; i++)
364 ser.syncAsSint16LE(audioBuffer[i]);
365 _audioStream = Audio::makeQueuingAudioStream(22050, false);
366 _audioStream->queueBuffer((byte *)audioBuffer, numSamples * 2, DisposeAfterUse::YES, Audio::FLAG_16BITS);
367 if (!_mixer->isSoundHandleActive(_soundHandle))
368 _mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _audioStream);
369
370 return Common::kNoError;
371 }
372
saveGameState(int slot,const Common::String & desc,bool isAutosave)373 Common::Error ComposerEngine::saveGameState(int slot, const Common::String &desc, bool isAutosave) {
374 Common::String filename = getSaveStateName(slot);
375 Common::OutSaveFile *out;
376 if (!(out = _saveFileMan->openForSaving(filename)))
377 return Common::kWritingFailed;
378
379 Common::Serializer ser(NULL, out);
380 byte magic[4] = {'C', 'M', 'P', 'S'};
381 ser.syncBytes(magic, 4);
382 ser.syncVersion(0);
383 Common::String desctmp = desc;
384 ser.syncString(desctmp);
385 uint32 tmp = _rnd->getSeed();
386 ser.syncAsUint32LE(tmp);
387 ser.syncAsUint32LE(_currentTime);
388 ser.syncAsUint32LE(_lastTime);
389
390 syncListReverse<Library>(ser, _libraries);
391 ser.syncString(_bookGroup);
392
393 syncArray<PendingPageChange>(ser, _pendingPageChanges);
394 syncArray<uint16>(ser, _stack);
395 syncArray<uint16>(ser, _vars);
396 syncList<OldScript *>(ser, _oldScripts);
397 syncArray<QueuedScript>(ser, _queuedScripts);
398
399 ser.syncAsSint16LE(_lastMousePos.x);
400 ser.syncAsSint16LE(_lastMousePos.y);
401 ser.syncAsByte(_mouseEnabled);
402 ser.syncAsByte(_mouseVisible);
403 ser.syncAsUint16LE(_mouseSpriteId);
404
405 syncListReverse<Pipe *>(ser, _pipes);
406 syncList<Animation *>(ser, _anims);
407 syncList<Sprite>(ser, _sprites);
408
409 byte paletteBuffer[256 * 3];
410 _system->getPaletteManager()->grabPalette(paletteBuffer, 0, 256);
411 ser.syncBytes(paletteBuffer, 256 * 3);
412
413 ser.syncAsSint16LE(_currSoundPriority);
414 int16 audioBuffer[22050];
415 int32 numSamples = _audioStream->readBuffer(audioBuffer, 22050);
416 if (numSamples == -1) numSamples = 0;
417 ser.syncAsSint32LE(numSamples);
418 for (int32 i = 0; i < numSamples; i++)
419 ser.syncAsSint16LE(audioBuffer[i]);
420
421 out->finalize();
422 return Common::kNoError;
423 }
424 } // End of namespace Composer
425