From 13d9cdbd26b1c07edf47b9e4731b9d652a294ba5 Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Fri, 3 Nov 2006 21:23:07 +0000 Subject: added 'touche' engine for the game 'Touche: The Adventures of the 5th Musketeer' svn-id: r24592 --- engines/touche/saveload.cpp | 418 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 engines/touche/saveload.cpp (limited to 'engines/touche/saveload.cpp') 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 +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 +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 +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 +static void saveOrLoad(S &s, SequenceEntry &seq) { + saveOrLoad(s, seq.sprNum); + saveOrLoad(s, seq.seqNum); +} + +template +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 +static void saveOrLoad(S &s, TalkEntry &entry) { + saveOrLoad(s, entry.otherKeyChar); + saveOrLoad(s, entry.talkingKeyChar); + saveOrLoad(s, entry.num); +} + +template +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 +static void saveOrLoad(S &s, Area &area) { + saveOrLoad(s, area.r); + saveOrLoad(s, area.srcX); + saveOrLoad(s, area.srcY); +} + +template +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 +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 +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 +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(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 -- cgit v1.2.3