diff options
| author | Gregory Montoir | 2006-11-03 21:23:07 +0000 | 
|---|---|---|
| committer | Gregory Montoir | 2006-11-03 21:23:07 +0000 | 
| commit | 13d9cdbd26b1c07edf47b9e4731b9d652a294ba5 (patch) | |
| tree | 4ecb39b0e40f592b36fbd5ef427e2ad4ea29ebd1 /engines/touche/saveload.cpp | |
| parent | c71e6599bc160329319c0c05ca453184a45fb0f7 (diff) | |
| download | scummvm-rg350-13d9cdbd26b1c07edf47b9e4731b9d652a294ba5.tar.gz scummvm-rg350-13d9cdbd26b1c07edf47b9e4731b9d652a294ba5.tar.bz2 scummvm-rg350-13d9cdbd26b1c07edf47b9e4731b9d652a294ba5.zip | |
added 'touche' engine for the game 'Touche: The Adventures of the 5th Musketeer'
svn-id: r24592
Diffstat (limited to 'engines/touche/saveload.cpp')
| -rw-r--r-- | engines/touche/saveload.cpp | 418 | 
1 files changed, 418 insertions, 0 deletions
| diff --git a/engines/touche/saveload.cpp b/engines/touche/saveload.cpp new file mode 100644 index 0000000000..e46ec24a30 --- /dev/null +++ b/engines/touche/saveload.cpp @@ -0,0 +1,418 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2006 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id: $ + * + */ + +#include "common/stdafx.h" +#include "common/savefile.h" + +#include "touche/graphics.h" +#include "touche/touche.h" + +namespace Touche { + +enum { +	kCurrentGameStateVersion = 5, +	kGameStateDescriptionLen = 32 +}; + +template <class S, class T> +static void saveOrLoad(S &s, T &t); + +template <> +static void saveOrLoad(Common::WriteStream &stream, uint16 &i) { +	stream.writeUint16LE(i); +} + +template <> +static void saveOrLoad(Common::ReadStream &stream, uint16 &i) { +	i = stream.readUint16LE(); +} + +template <> +static void saveOrLoad(Common::WriteStream &stream, int16 &i) { +	stream.writeSint16LE(i); +} + +template <> +static void saveOrLoad(Common::ReadStream &stream, int16 &i) { +	i = stream.readSint16LE(); +} + +template <class S, class T> +static void saveOrLoadPtr(S &s, T *&t, T *base); + +template <> +static void saveOrLoadPtr(Common::WriteStream &stream, int16 *&p, int16 *base) { +	int32 offset = (int32)(p - base); +	stream.writeSint32LE(offset); +} + +template <> +static void saveOrLoadPtr(Common::ReadStream &stream, int16 *&p, int16 *base) { +	int32 offset = stream.readSint32LE(); +	p = base + offset; +} + +template <class S> +static void saveOrLoad(S &s, Common::Rect &r) { +	saveOrLoad(s, r.left); +	saveOrLoad(s, r.top); +	saveOrLoad(s, r.right); +	saveOrLoad(s, r.bottom); +} + +template <class S> +static void saveOrLoad(S &s, SequenceEntry &seq) { +	saveOrLoad(s, seq.sprNum); +	saveOrLoad(s, seq.seqNum); +} + +template <class S> +static void saveOrLoad(S &s, KeyChar &key) { +	saveOrLoad(s, key.num); +	saveOrLoad(s, key.flags); +	saveOrLoad(s, key.currentAnimCounter); +	saveOrLoad(s, key.strNum); +	saveOrLoad(s, key.walkDataNum); +	saveOrLoad(s, key.spriteNum); +	saveOrLoad(s, key.prevBoundingRect); +	saveOrLoad(s, key.boundingRect); +	saveOrLoad(s, key.xPos); +	saveOrLoad(s, key.yPos); +	saveOrLoad(s, key.zPos); +	saveOrLoad(s, key.xPosPrev); +	saveOrLoad(s, key.yPosPrev); +	saveOrLoad(s, key.zPosPrev); +	saveOrLoad(s, key.prevWalkDataNum); +	saveOrLoad(s, key.textColor); +	for (uint i = 0; i < 4; ++i) { +		saveOrLoad(s, key.inventoryItems[i]); +	} +	saveOrLoad(s, key.money); +	saveOrLoad(s, key.pointsDataNum); +	saveOrLoad(s, key.currentWalkBox); +	saveOrLoad(s, key.prevPointsDataNum); +	saveOrLoad(s, key.currentAnim); +	saveOrLoad(s, key.facingDirection); +	saveOrLoad(s, key.currentAnimSpeed); +	for (uint i = 0; i < 16; ++i) { +		saveOrLoad(s, key.framesList[i]); +	} +	saveOrLoad(s, key.framesListCount); +	saveOrLoad(s, key.currentFrame); +	saveOrLoad(s, key.anim1Start); +	saveOrLoad(s, key.anim1Count); +	saveOrLoad(s, key.anim2Start); +	saveOrLoad(s, key.anim2Count); +	saveOrLoad(s, key.anim3Start); +	saveOrLoad(s, key.anim3Count); +	saveOrLoad(s, key.followingKeyCharNum); +	saveOrLoad(s, key.followingKeyCharPos); +	saveOrLoad(s, key.sequenceDataIndex); +	saveOrLoad(s, key.sequenceDataOffset); +	saveOrLoad(s, key.walkPointsListCount); +	for (uint i = 0; i < 40; ++i) { +		saveOrLoad(s, key.walkPointsList[i]); +	} +	saveOrLoad(s, key.scriptDataStartOffset); +	saveOrLoad(s, key.scriptDataOffset); +	saveOrLoadPtr(s, key.scriptStackPtr, &key.scriptStackTable[39]); +	saveOrLoad(s, key.delay); +	saveOrLoad(s, key.waitingKeyChar); +	for (uint i = 0; i < 3; ++i) { +		saveOrLoad(s, key.waitingKeyCharPosTable[i]); +	} +	for (uint i = 0; i < 40; ++i) { +		saveOrLoad(s, key.scriptStackTable[i]); +	} +} + +template <class S> +static void saveOrLoad(S &s, TalkEntry &entry) { +	saveOrLoad(s, entry.otherKeyChar); +	saveOrLoad(s, entry.talkingKeyChar); +	saveOrLoad(s, entry.num); +} + +template <class S> +static void saveOrLoad(S &s, ProgramHitBoxData &data) { +	saveOrLoad(s, data.item); +	saveOrLoad(s, data.talk); +	saveOrLoad(s, data.state); +	saveOrLoad(s, data.str); +	saveOrLoad(s, data.defaultStr); +	for (uint i = 0; i < 8; ++i) { +		saveOrLoad(s, data.actions[i]); +	} +	for (uint i = 0; i < 2; ++i) { +		saveOrLoad(s, data.hitBoxes[i]); +	} +} + +template <class S> +static void saveOrLoad(S &s, Area &area) { +	saveOrLoad(s, area.r); +	saveOrLoad(s, area.srcX); +	saveOrLoad(s, area.srcY); +} + +template <class S> +static void saveOrLoad(S &s, ProgramBackgroundData &data) { +	saveOrLoad(s, data.area); +	saveOrLoad(s, data.type); +	saveOrLoad(s, data.offset); +	saveOrLoad(s, data.scaleMul); +	saveOrLoad(s, data.scaleDiv); +} + +template <class S> +static void saveOrLoad(S &s, ProgramAreaData &data) { +	saveOrLoad(s, data.area); +	saveOrLoad(s, data.id); +	saveOrLoad(s, data.state); +	saveOrLoad(s, data.animCount); +	saveOrLoad(s, data.animNext); +} + +template <class S> +static void saveOrLoad(S &s, ProgramWalkData &data) { +	saveOrLoad(s, data.point1); +	saveOrLoad(s, data.point2); +	saveOrLoad(s, data.clippingRect); +	saveOrLoad(s, data.area1); +	saveOrLoad(s, data.area2); +} + +template <class S> +static void saveOrLoad(S &s, ProgramPointData &data) { +	saveOrLoad(s, data.x); +	saveOrLoad(s, data.y); +	saveOrLoad(s, data.z); +	saveOrLoad(s, data.priority); +} + +void ToucheEngine::saveGameStateData(Common::WriteStream *stream) { +	setKeyCharMoney(); +	stream->writeUint16LE(_currentEpisodeNum); +	stream->writeUint16LE(_currentMusicNum); +	stream->writeUint16LE(_currentRoomNum); +	stream->writeUint16LE(_flagsTable[614]); +	stream->writeUint16LE(_flagsTable[615]); +	stream->writeUint16LE(_disabledInputCounter); +	for (uint i = 0; i < _programHitBoxTable.size(); ++i) { +		saveOrLoad(*stream, _programHitBoxTable[i]); +	} +	for (uint i = 0; i < _programBackgroundTable.size(); ++i) { +		saveOrLoad(*stream, _programBackgroundTable[i]); +	} +	for (uint i = 0; i < _programAreaTable.size(); ++i) { +		saveOrLoad(*stream, _programAreaTable[i]); +	} +	for (uint i = 0; i < _programWalkTable.size(); ++i) { +		saveOrLoad(*stream, _programWalkTable[i]); +	} +	for (uint i = 0; i < _programPointsTable.size(); ++i) { +		saveOrLoad(*stream, _programPointsTable[i]); +	} +	stream->write(_updatedRoomAreasTable, 200); +	for (uint i = 0; i < 6; ++i) { +		saveOrLoad(*stream, _sequenceEntryTable[i]); +	} +	for (uint i = 0; i < 1024; ++i) { +		saveOrLoad(*stream, _flagsTable[i]); +	} +	for (uint i = 0; i < 100; ++i) { +		saveOrLoad(*stream, _inventoryList1[i]); +	} +	for (uint i = 0; i < 100; ++i) { +		saveOrLoad(*stream, _inventoryList2[i]); +	} +	for (uint i = 0; i < 6; ++i) { +		saveOrLoad(*stream, _inventoryList3[i]); +	} +	for (uint i = 0; i < NUM_KEYCHARS; ++i) { +		saveOrLoad(*stream, _keyCharsTable[i]); +	} +	for (uint i = 0; i < NUM_INVENTORY_ITEMS; ++i) { +		saveOrLoad(*stream, _inventoryItemsInfoTable[i]); +	} +	for (uint i = 0; i < NUM_TALK_ENTRIES; ++i) { +		saveOrLoad(*stream, _talkTable[i]); +	} +	stream->writeUint16LE(_talkListEnd); +	stream->writeUint16LE(_talkListCurrent); +} + +void ToucheEngine::loadGameStateData(Common::ReadStream *stream) { +	setKeyCharMoney(); +	clearDirtyRects(); +	clearAreaTable(); +	_flagsTable[115] = 0; +	clearRoomArea(); +	int16 room_offs_x, room_offs_y; +	_currentEpisodeNum = stream->readUint16LE(); +	_currentMusicNum = stream->readUint16LE(); +	_currentRoomNum = stream->readUint16LE(); +	res_loadRoom(_currentRoomNum); +	room_offs_x = stream->readUint16LE(); +	room_offs_y = stream->readUint16LE(); +	_disabledInputCounter = stream->readUint16LE(); +	res_loadProgram(_currentEpisodeNum); +	setupEpisode(-1); +	for (uint i = 0; i < _programHitBoxTable.size(); ++i) { +		saveOrLoad(*stream, _programHitBoxTable[i]); +	} +	for (uint i = 0; i < _programBackgroundTable.size(); ++i) { +		saveOrLoad(*stream, _programBackgroundTable[i]); +	} +	for (uint i = 0; i < _programAreaTable.size(); ++i) { +		saveOrLoad(*stream, _programAreaTable[i]); +	} +	for (uint i = 0; i < _programWalkTable.size(); ++i) { +		saveOrLoad(*stream, _programWalkTable[i]); +	} +	for (uint i = 0; i < _programPointsTable.size(); ++i) { +		saveOrLoad(*stream, _programPointsTable[i]); +	} +	stream->read(_updatedRoomAreasTable, 200); +	for (uint i = 1; i <= _updatedRoomAreasTable[0]; ++i) { +		updateRoomAreas(_updatedRoomAreasTable[i], -1); +	} +	for (uint i = 0; i < 6; ++i) { +		saveOrLoad(*stream, _sequenceEntryTable[i]); +	} +	for (uint i = 0; i < 1024; ++i) { +		saveOrLoad(*stream, _flagsTable[i]); +	} +	for (uint i = 0; i < 100; ++i) { +		saveOrLoad(*stream, _inventoryList1[i]); +	} +	for (uint i = 0; i < 100; ++i) { +		saveOrLoad(*stream, _inventoryList2[i]); +	} +	for (uint i = 0; i < 6; ++i) { +		saveOrLoad(*stream, _inventoryList3[i]); +	} +	for (uint i = 0; i < NUM_KEYCHARS; ++i) { +		saveOrLoad(*stream, _keyCharsTable[i]); +	} +	for (uint i = 0; i < NUM_INVENTORY_ITEMS; ++i) { +		saveOrLoad(*stream, _inventoryItemsInfoTable[i]); +	} +	for (uint i = 0; i < NUM_TALK_ENTRIES; ++i) { +		saveOrLoad(*stream, _talkTable[i]); +	} +	_talkListEnd = stream->readUint16LE(); +	_talkListCurrent = stream->readUint16LE(); +	_flagsTable[614] = room_offs_x; +	_flagsTable[615] = room_offs_y; +	for (uint i = 0; i < 6; ++i) { +		if (_sequenceEntryTable[i].seqNum != -1) { +			res_loadSequence(_sequenceEntryTable[i].seqNum, i); +		} +		if (_sequenceEntryTable[i].sprNum != -1) { +			res_loadSprite(_sequenceEntryTable[i].sprNum, i); +		} +	} +	_currentKeyCharNum = _flagsTable[104]; +	_inventoryListCount[0] = 0; +	_inventoryListCount[3] = 0; +	_inventoryListCount[6] = 0; +	drawInventory(_currentKeyCharNum, 1); +	Graphics::copyRect(_offscreenBuffer, 640, 0, 0, _backdropBuffer, _currentBitmapWidth, _flagsTable[614], _flagsTable[615], 640, 352); +	updateEntireScreen(); +	if (_flagsTable[617] != 0) { +		res_loadSpeech(_flagsTable[617]); +	} +} + +bool ToucheEngine::saveGameState(int num, const char *description) { +	bool saveOk = false; +	char gameStateFileName[16]; +	generateGameStateFileName(num, gameStateFileName, 15); +	Common::OutSaveFile *f = _saveFileMan->openForSaving(gameStateFileName); +	if (f) { +		f->writeUint16LE(kCurrentGameStateVersion); +		f->writeUint16LE(0); +		char headerDescription[kGameStateDescriptionLen]; +		memset(headerDescription, 0, kGameStateDescriptionLen); +		strncpy(headerDescription, description, kGameStateDescriptionLen - 1); +		f->write(headerDescription, kGameStateDescriptionLen); +		saveGameStateData(f); +		f->flush(); +		if (!f->ioFailed()) { +			saveOk = true; +		} else { +			warning("Can't write file '%s'", gameStateFileName); +		} +		delete f; +	} +	return saveOk; +} + +bool ToucheEngine::loadGameState(int num, const char *description) { +	bool loadOk = false; +	char gameStateFileName[16]; +	generateGameStateFileName(num, gameStateFileName, 15); +	Common::InSaveFile *f = _saveFileMan->openForLoading(gameStateFileName); +	if (f) { +		uint16 version = f->readUint16LE(); +		if (version < kCurrentGameStateVersion) { +			warning("Unsupported gamestate version %d\n", version); +		} else { +			f->skip(2 + kGameStateDescriptionLen); +			loadGameStateData(f); +			if (!f->ioFailed()) { +				loadOk = true; +			} else { +				warning("Can't read file '%s'", gameStateFileName); +			} +		} +		delete f; +	} +	return loadOk; +} + +void ToucheEngine::readGameStateDescription(int num, char *description, int len) { +	char gameStateFileName[16]; +	generateGameStateFileName(num, gameStateFileName, 15); +	Common::InSaveFile *f = _saveFileMan->openForLoading(gameStateFileName); +	if (f) { +		uint16 version = f->readUint16LE(); +		if (version >= kCurrentGameStateVersion) { +			f->readUint16LE(); +			f->read(description, MIN<int>(len, kGameStateDescriptionLen)); +			description[len] = 0; +		} +		delete f; +	} +} + +void ToucheEngine::generateGameStateFileName(int num, char *dst, int len, bool prefixOnly) const { +	if (prefixOnly) { +		snprintf(dst, len, "%s.", _targetName.c_str()); +	} else { +		snprintf(dst, len, "%s.%d", _targetName.c_str(), num); +	} +	dst[len] = 0; +} + +} // namespace Touche | 
