From 283a9f35ac294fa10105c7d8c18b57d7a2689e19 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Thu, 21 Apr 2005 01:30:07 +0000 Subject: Add not yet correctly working save/load. Use key F7 for saving and F8 for loading. Now works only within current scene and restores to entrance #0 which is wrong. svn-id: r17726 --- saga/actor.cpp | 6 ++ saga/actor.h | 7 +- saga/input.cpp | 6 ++ saga/interface.cpp | 15 ++++- saga/interface.h | 3 +- saga/isomap.h | 1 + saga/module.mk | 1 + saga/saga.h | 3 + saga/saveload.cpp | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++ saga/scene.cpp | 19 ++++-- saga/scene.h | 2 + saga/script.h | 10 ++- saga/sfuncs.cpp | 9 ++- 13 files changed, 257 insertions(+), 17 deletions(-) create mode 100644 saga/saveload.cpp (limited to 'saga') diff --git a/saga/actor.cpp b/saga/actor.cpp index 0926fdb2f4..77cb38fe59 100644 --- a/saga/actor.cpp +++ b/saga/actor.cpp @@ -180,6 +180,7 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { _pathDirectionListAlloced = 0; _centerActor = _protagonist = NULL; + _protagState = 0; _lastTickMsec = 0; _yCellCount = _vm->getSceneHeight(); @@ -548,6 +549,11 @@ bool Actor::validFollowerLocation(const Location &location) { return (_vm->_scene->canWalk(point)); } +void Actor::setProtagState(int state) { + debug(0, "STUB: setProtagState(%d)", state); + _protagState = state; +} + void Actor::updateActorsScene(int actorsEntrance) { int i, j; int followerDirection; diff --git a/saga/actor.h b/saga/actor.h index 93e3f2a803..c734f4c1ad 100644 --- a/saga/actor.h +++ b/saga/actor.h @@ -382,6 +382,9 @@ public: bool isSpeaking() { return _activeSpeech.stringsCount > 0; } + + void setProtagState(int state); + int getProtagState() { return _protagState; } private: bool loadActorResources(ActorData *actor); @@ -428,14 +431,16 @@ private: protected: friend class IsoMap; + friend class SagaEngine; int _actorsCount; ActorData **_actors; -private: int _objsCount; ObjectData **_objs; +private: SpeechData _activeSpeech; + int _protagState; //path stuff struct PathNode { diff --git a/saga/input.cpp b/saga/input.cpp index 56139ae932..c93a5782be 100644 --- a/saga/input.cpp +++ b/saga/input.cpp @@ -84,6 +84,12 @@ int SagaEngine::processInput() { case 287: // F6 _render->toggleFlag(RF_ACTOR_PATH_TEST); break; + case 288: // F7 + save(); + break; + case 289: // F8 + load(); + break; case 9: // Tab _script->SThreadDebugStep(); break; diff --git a/saga/interface.cpp b/saga/interface.cpp index 361254b81b..2e27612de2 100644 --- a/saga/interface.cpp +++ b/saga/interface.cpp @@ -506,7 +506,13 @@ PanelButton *Interface::verbHitTest(const Point& mousePoint) { return NULL; } -void Interface::addToInventory(int sprite) { +void Interface::addToInventory(int sprite, int pos) { + if (pos != -1) { + _inventory[pos] = sprite; + _inventoryCount++; + return; + } + if (_inventoryCount < _inventorySize) { for (int i = _inventoryCount; i > 0; i--) { _inventory[i] = _inventory[i - 1]; @@ -535,6 +541,13 @@ void Interface::removeFromInventory(int sprite) { } } +void Interface::clearInventory() { + for (int i = 0; i < _inventoryCount; i++) + _inventory[i] = 0; + + _inventoryCount = 0; +} + int Interface::inventoryItemPosition(int sprite) { for (int i = 0; i < _inventoryCount; i++) if (_inventory[i] == sprite) diff --git a/saga/interface.h b/saga/interface.h index 84c8322004..654e7dea7d 100644 --- a/saga/interface.h +++ b/saga/interface.h @@ -137,8 +137,9 @@ public: bool processKeyCode(int keyCode); - void addToInventory(int sprite); + void addToInventory(int sprite, int pos = -1); void removeFromInventory(int sprite); + void clearInventory(); int inventoryItemPosition(int sprite); void drawInventory(); diff --git a/saga/isomap.h b/saga/isomap.h index 971d53ba52..a59f559dcd 100644 --- a/saga/isomap.h +++ b/saga/isomap.h @@ -167,6 +167,7 @@ public: void findTilePath(ActorData* actor, const Location &start, const Location &end); bool nextTileTarget(ActorData* actor); void setTileDoorState(int doorNumber, int doorState); + Point getMapPosition() { return _mapPosition; } private: void drawTiles(SURFACE *ds, const Location *location); diff --git a/saga/module.mk b/saga/module.mk index d28f57c823..adbb632b66 100644 --- a/saga/module.mk +++ b/saga/module.mk @@ -20,6 +20,7 @@ MODULE_OBJS := \ saga/render.o \ saga/rscfile.o \ saga/saga.o \ + saga/saveload.o \ saga/scene.o \ saga/script.o \ saga/sdebug.o \ diff --git a/saga/saga.h b/saga/saga.h index a789bc9cc7..2c6dd0e614 100644 --- a/saga/saga.h +++ b/saga/saga.h @@ -425,6 +425,9 @@ public: virtual ~SagaEngine(); void shutDown() { _quit = true; } + void save(); + void load(); + int _soundEnabled; int _musicEnabled; diff --git a/saga/saveload.cpp b/saga/saveload.cpp new file mode 100644 index 0000000000..fd7f096104 --- /dev/null +++ b/saga/saveload.cpp @@ -0,0 +1,192 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004-2005 The ScummVM project + * + * The ReInherit Engine is (C)2000-2003 by Daniel Balsom. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ + +#include "stdafx.h" + +#include "common/config-manager.h" +#include "common/savefile.h" +#include "common/system.h" +#include "common/file.h" + +#include "saga/saga.h" +#include "saga/actor.h" +#include "saga/isomap.h" +#include "saga/resnames.h" +#include "saga/script.h" +#include "saga/interface.h" +#include "saga/scene.h" + +namespace Saga { + +void SagaEngine::save() { + File out; + + out.open("ite.sav", File::kFileWriteMode); + + out.writeSint16LE(_actor->_actorsCount); + out.writeSint16LE(_actor->_objsCount); + out.writeSint16LE(_script->_commonBufferSize); + out.writeSint16LE(_actor->getProtagState()); + + // Surrounding scene + out.writeSint32LE(_scene->getOutsetSceneNumber()); + out.writeSint32LE(0); + + // Inset scene + out.writeSint32LE(_scene->currentSceneNumber()); + out.writeSint32LE(0); + + uint16 i; + + for (i = 0; i < _actor->_actorsCount; i++) { + ActorData *a = _actor->_actors[i]; + + out.writeSint32LE(a->sceneNumber); + out.writeSint16LE(a->location.x); + out.writeSint16LE(a->location.y); + out.writeSint16LE(a->location.z); + out.writeSint16LE(a->finalTarget.x); + out.writeSint16LE(a->finalTarget.y); + out.writeSint16LE(a->finalTarget.z); + out.writeByte(a->currentAction); + out.writeByte(a->facingDirection); + out.writeSint16LE(a->targetObject); + out.writeByte(a->flags & (kProtagonist | kFollower)); + out.writeByte(a->frameNumber); + out.writeSint16LE(0); + } + + for (i = 0; i < _actor->_objsCount; i++) { + ObjectData *o = _actor->_objs[i]; + + out.writeSint32LE(o->sceneNumber); + out.writeSint32LE(o->id); + out.writeSint16LE(o->location.x); + out.writeSint16LE(o->location.y); + out.writeSint16LE(o->location.z); + out.writeSint16LE(o->nameIndex); + if (o->sceneNumber == ITE_SCENE_INV) { + out.writeSint16LE(_interface->inventoryItemPosition(_actor->objIndexToId(i))); + } else { + out.writeSint16LE(0); + } + out.writeByte(0); + } + + for (i = 0; i < _script->_commonBufferSize; i++) + out.writeByte(_script->_commonBuffer[i]); + + out.writeSint16LE(_isoMap->getMapPosition().x); + out.writeSint16LE(_isoMap->getMapPosition().y); + + out.close(); +} + +void SagaEngine::load() { + File out; + int actorsCount, objsCount, commonBufferSize; + int scenenum, inset; + + out.open("ite.sav"); + + if (!out.isOpen()) + return; + + actorsCount = out.readSint16LE(); + objsCount = out.readSint16LE(); + commonBufferSize = out.readSint16LE(); + _actor->setProtagState(out.readSint16LE()); + + // Surrounding scene + scenenum = out.readSint32LE(); + out.readSint32LE(); + + // Inset scene + inset = out.readSint32LE(); + out.readSint32LE(); + + uint16 i; + + for (i = 0; i < actorsCount; i++) { + ActorData *a = _actor->_actors[i]; + + a->sceneNumber = out.readSint32LE(); + a->location.x = out.readSint16LE(); + a->location.y = out.readSint16LE(); + a->location.z = out.readSint16LE(); + a->finalTarget.x = out.readSint16LE(); + a->finalTarget.y = out.readSint16LE(); + a->finalTarget.z = out.readSint16LE(); + a->currentAction = out.readByte(); + a->facingDirection = out.readByte(); + a->targetObject = out.readSint16LE(); + a->flags = (a->flags & ~(kProtagonist | kFollower) | out.readByte()); + a->frameNumber = out.readByte(); + out.readSint16LE(); + } + + _interface->clearInventory(); + + for (i = 0; i < objsCount; i++) { + ObjectData *o = _actor->_objs[i]; + int pos; + + o->sceneNumber = out.readSint32LE(); + o->id = out.readSint32LE(); + o->location.x = out.readSint16LE(); + o->location.y = out.readSint16LE(); + o->location.z = out.readSint16LE(); + o->nameIndex = out.readSint16LE(); + + pos = out.readSint16LE(); + if (o->sceneNumber == ITE_SCENE_INV) { + _interface->addToInventory(_actor->objIndexToId(i), pos); + } + out.readByte(); + } + + for (i = 0; i < commonBufferSize; i++) + _script->_commonBuffer[i] = out.readByte(); + + _isoMap->getMapPosition().x = out.readSint16LE(); + _isoMap->getMapPosition().y = out.readSint16LE(); + + out.close(); + + + // FIXME: When save/load screen will be implemented we should + // call these after that screen left by user + _interface->draw(); + + // FIXME: hmmm... now we always require actorsEntrance to be defined + // so no way to restore at arbitrary position + _scene->clearSceneQueue(); + _scene->changeScene(scenenum, 0); + + if (inset != scenenum) { + _scene->clearSceneQueue(); + _scene->changeScene(inset, 0); + } +} + +} // End of namespace Saga diff --git a/saga/scene.cpp b/saga/scene.cpp index c03263fb37..2c0b0b5b0a 100644 --- a/saga/scene.cpp +++ b/saga/scene.cpp @@ -581,6 +581,13 @@ int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SceneD return FAILURE; } + if (_desc.flags & kSceneFlagISO) { + _outsetSceneNumber = _sceneNumber; + } else { + if (!(_bg.w < _vm->getDisplayWidth() || _bg.h < _vm->getSceneHeight())) + _outsetSceneNumber = _sceneNumber; + } + _sceneLoaded = true; q_event = NULL; @@ -875,7 +882,7 @@ int Scene::processSceneResources() { _actionMap->load(res_data, res_data_len); break; case SAGA_ISO_IMAGES: - if (!(_vm->_scene->getFlags() & kSceneFlagISO)) { + if (!(_desc.flags & kSceneFlagISO)) { error("Scene::ProcessSceneResources(): not Iso mode"); } @@ -884,7 +891,7 @@ int Scene::processSceneResources() { _vm->_isoMap->loadImages(res_data, res_data_len); break; case SAGA_ISO_MAP: - if (!(_vm->_scene->getFlags() & kSceneFlagISO)) { + if (!(_desc.flags & kSceneFlagISO)) { error("Scene::ProcessSceneResources(): not Iso mode"); } @@ -893,7 +900,7 @@ int Scene::processSceneResources() { _vm->_isoMap->loadMap(res_data, res_data_len); break; case SAGA_ISO_PLATFORMS: - if (!(_vm->_scene->getFlags() & kSceneFlagISO)) { + if (!(_desc.flags & kSceneFlagISO)) { error("Scene::ProcessSceneResources(): not Iso mode"); } @@ -902,7 +909,7 @@ int Scene::processSceneResources() { _vm->_isoMap->loadPlatforms(res_data, res_data_len); break; case SAGA_ISO_METATILES: - if (!(_vm->_scene->getFlags() & kSceneFlagISO)) { + if (!(_desc.flags & kSceneFlagISO)) { error("Scene::ProcessSceneResources(): not Iso mode"); } @@ -938,7 +945,7 @@ int Scene::processSceneResources() { } break; case SAGA_ISO_MULTI: - if (!(_vm->_scene->getFlags() & kSceneFlagISO)) { + if (!(_desc.flags & kSceneFlagISO)) { error("Scene::ProcessSceneResources(): not Iso mode"); } @@ -973,7 +980,7 @@ int Scene::draw(SURFACE *dst_s) { _vm->_render->getBufferInfo(&buf_info); - if (_vm->_scene->getFlags() & kSceneFlagISO) { + if (_desc.flags & kSceneFlagISO) { _vm->_isoMap->adjustScroll(false); _vm->_isoMap->draw(dst_s); } else { diff --git a/saga/scene.h b/saga/scene.h index df0c1344e1..7405bcea77 100644 --- a/saga/scene.h +++ b/saga/scene.h @@ -261,6 +261,7 @@ class Scene { int getSceneLUT(int num); int currentSceneNumber() const { return _sceneNumber; } + int getOutsetSceneNumber() const { return _outsetSceneNumber; } int currentSceneResourceId() const { return _sceneResourceId; } private: @@ -282,6 +283,7 @@ class Scene { int _firstScene; bool _sceneLoaded; int _sceneNumber; + int _outsetSceneNumber; int _sceneResourceId; bool _inGame; bool _loadDesc; diff --git a/saga/script.h b/saga/script.h index 4fa8feb3d1..d115116f1f 100644 --- a/saga/script.h +++ b/saga/script.h @@ -389,9 +389,13 @@ private: uint16 _modulesLUTEntryLen; ModuleData *_modules; int _modulesCount; - - byte* _commonBuffer; + +protected: + friend class SagaEngine; + byte *_commonBuffer; uint _commonBufferSize; + +private: uint _staticSize; ScriptThreadList _threadList; @@ -508,7 +512,7 @@ private: void SF_simulSpeech2(SCRIPTFUNC_PARAMS); void sfPlacard(SCRIPTFUNC_PARAMS); void sfPlacardOff(SCRIPTFUNC_PARAMS); - void SF_setProtagState(SCRIPTFUNC_PARAMS); + void sfSetProtagState(SCRIPTFUNC_PARAMS); void sfResumeBgdAnim(SCRIPTFUNC_PARAMS); void SF_throwActor(SCRIPTFUNC_PARAMS); void sfWaitWalk(SCRIPTFUNC_PARAMS); diff --git a/saga/sfuncs.cpp b/saga/sfuncs.cpp index 4a2eaf81e8..07c5dd947c 100644 --- a/saga/sfuncs.cpp +++ b/saga/sfuncs.cpp @@ -100,7 +100,7 @@ void Script::setupScriptFuncList(void) { OPCODE(SF_simulSpeech2), OPCODE(sfPlacard), OPCODE(sfPlacardOff), - OPCODE(SF_setProtagState), + OPCODE(sfSetProtagState), OPCODE(sfResumeBgdAnim), OPCODE(SF_throwActor), OPCODE(sfWaitWalk), @@ -1305,11 +1305,10 @@ void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) { } // Script function #50 (0x32) -void Script::SF_setProtagState(SCRIPTFUNC_PARAMS) { - for (int i = 0; i < nArgs; i++) - thread->pop(); +void Script::sfSetProtagState(SCRIPTFUNC_PARAMS) { + int protagState = thread->pop(); - debug(0, "STUB: SF_setProtagState(), %d args", nArgs); + _vm->_actor->setProtagState(protagState); } // Script function #51 (0x33) -- cgit v1.2.3