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