From c848548c027ffd2cca2de333490757019a0f59e5 Mon Sep 17 00:00:00 2001 From: Eric Fry Date: Mon, 13 May 2019 08:21:48 +1000 Subject: [PATCH] DRAGONS: work on save/load --- engines/dragons/cursor.cpp | 5 +- engines/dragons/cursor.h | 1 + engines/dragons/dragonflg.cpp | 48 ++++++-- engines/dragons/dragonflg.h | 10 +- engines/dragons/dragonini.cpp | 15 ++- engines/dragons/dragonini.h | 2 + engines/dragons/dragons.cpp | 124 +++++++++---------- engines/dragons/dragons.h | 11 +- engines/dragons/dragonvar.cpp | 15 ++- engines/dragons/dragonvar.h | 2 + engines/dragons/saveload.cpp | 184 +++++++++++++++++++++++++++++ engines/dragons/scriptopcodes.cpp | 6 +- engines/dragons/specialopcodes.cpp | 7 ++ engines/dragons/specialopcodes.h | 1 + 14 files changed, 339 insertions(+), 92 deletions(-) create mode 100644 engines/dragons/saveload.cpp diff --git a/engines/dragons/cursor.cpp b/engines/dragons/cursor.cpp index 98057d05892..61adaeffd5a 100644 --- a/engines/dragons/cursor.cpp +++ b/engines/dragons/cursor.cpp @@ -51,6 +51,7 @@ void Cursor::init(ActorManager *actorManager, DragonINIResource *dragonINIResour dragonINIResource->getFlickerRecord()->actor = _actor; //TODO is this correct? dragonINIResource->getFlickerRecord()->field_1a_flags_maybe |= Dragons::INI_FLAG_1; _iniUnderCursor = 0; + iniItemInHand = 0; data_8007283c = 0; _cursorActivationSeqOffset = 0; data_800728b0_cursor_seqID = 0; @@ -116,7 +117,7 @@ void Cursor::update() { } } - if (_vm->iniItemInHand == 0) { + if (iniItemInHand == 0) { if (_actor->_sequenceID != 0x84) { _actor->updateSequence(0x84); } @@ -331,7 +332,7 @@ void Cursor::selectPreviousCursor() { _sequenceID = 0x10001; } if (_sequenceID == -1) { - _sequenceID = _vm->iniItemInHand == 0 ? 4 : 5; + _sequenceID = iniItemInHand == 0 ? 4 : 5; } } diff --git a/engines/dragons/cursor.h b/engines/dragons/cursor.h index b2be91c4d4a..d9c78fceeb7 100644 --- a/engines/dragons/cursor.h +++ b/engines/dragons/cursor.h @@ -42,6 +42,7 @@ public: int16 _y; int16 data_8007283c; int16 _cursorActivationSeqOffset; + uint16 iniItemInHand; private: DragonsEngine *_vm; Actor *_actor; diff --git a/engines/dragons/dragonflg.cpp b/engines/dragons/dragonflg.cpp index e1d7bdc2e1a..501500b7d5f 100644 --- a/engines/dragons/dragonflg.cpp +++ b/engines/dragons/dragonflg.cpp @@ -27,13 +27,22 @@ namespace Dragons { // Properties -Properties::Properties() - : _count(0), _properties(0) { +Properties::Properties(uint count) + : _count(count) { + _properties = (byte *)malloc(getSize()); + if(!_properties) { + error("Failed to allocate mem for properties"); + } + memset(_properties, 0, getSize()); +} + +Properties::~Properties() { + free(_properties); } void Properties::init(uint count, byte *properties) { - _count = count; - _properties = properties; + assert(count <= getSize()); + memcpy(_properties, properties, count); } void Properties::clear() { @@ -71,23 +80,42 @@ void Properties::getProperyPos(uint32 propertyId, uint &index, byte &mask) { mask = 1 << (propertyId & 7); } +void Properties::save(uint numberToWrite, Common::WriteStream *out) { + assert(numberToWrite % 8 == 0); + assert(numberToWrite <= _count); + out->write(_properties, numberToWrite / 8); +} + DragonFLG::DragonFLG(BigfileArchive *bigfileArchive) { _data = bigfileArchive->load("dragon.flg", _dataSize); - properties.init(288, _data); + properties = new Properties(288); + properties->init(_dataSize, _data); } DragonFLG::~DragonFLG() { - if (_data) { - delete _data; - } + delete _data; } bool DragonFLG::get(uint32 propertyId) { - return properties.get(propertyId); + return properties->get(propertyId); } void DragonFLG::set(uint32 propertyId, bool value) { - properties.set(propertyId, value); + properties->set(propertyId, value); +} + +void DragonFLG::saveState(Common::WriteStream *out) { + properties->save(128, out); // save first 80 flags. +} + +void DragonFLG::loadState(Common::ReadStream *in) { + byte savedState[0x10]; + + properties->init(_dataSize, _data); + + in->read(savedState, 0x10); + properties->init(0x10, savedState); + } } // End of namespace Dragons diff --git a/engines/dragons/dragonflg.h b/engines/dragons/dragonflg.h index c2e3a873fd6..0a5049687ef 100644 --- a/engines/dragons/dragonflg.h +++ b/engines/dragons/dragonflg.h @@ -22,6 +22,7 @@ #ifndef SCUMMVM_DRAGONFLG_H #define SCUMMVM_DRAGONFLG_H +#include "common/stream.h" #include "common/system.h" namespace Dragons { @@ -30,11 +31,13 @@ class BigfileArchive; class Properties { public: - Properties(); + Properties(uint count); + ~Properties(); void init(uint count, byte *properties); void clear(); bool get(uint32 propertyId); void set(uint32 propertyId, bool value); + void save(uint numberToWrite, Common::WriteStream *out); private: uint _count; byte *_properties; @@ -46,13 +49,16 @@ class DragonFLG { private: byte *_data; uint32_t _dataSize; - Properties properties; + Properties *properties; public: virtual ~DragonFLG(); DragonFLG(BigfileArchive *bigfileArchive); bool get(uint32 propertyId); void set(uint32 propertyId, bool value); + + void saveState(Common::WriteStream *out); + void loadState(Common::ReadStream *in); }; } // End of namespace Dragons diff --git a/engines/dragons/dragonini.cpp b/engines/dragons/dragonini.cpp index f3874003f81..35316d7583d 100644 --- a/engines/dragons/dragonini.cpp +++ b/engines/dragons/dragonini.cpp @@ -26,14 +26,19 @@ namespace Dragons { #define DRAGON_INI_STRUCT_SIZE 0x22 -DragonINIResource::DragonINIResource(BigfileArchive *bigfileArchive) { +DragonINIResource::DragonINIResource(BigfileArchive *bigfileArchive): _bigfileArchive(bigfileArchive), _dragonINI(0) { + reset(); +} + +void DragonINIResource::reset() { uint32 fileSize; - byte *data = bigfileArchive->load("dragon.ini", fileSize); + byte *data = _bigfileArchive->load("dragon.ini", fileSize); Common::SeekableReadStream *readStream = new Common::MemoryReadStream(data, fileSize, DisposeAfterUse::YES); - _count = fileSize / DRAGON_INI_STRUCT_SIZE; - - _dragonINI = new DragonINI[_count]; + if (!_dragonINI) { + _count = fileSize / DRAGON_INI_STRUCT_SIZE; + _dragonINI = new DragonINI[_count]; + } for(int i=0; i < _count; i++) { _dragonINI[i].id = (uint16)i; diff --git a/engines/dragons/dragonini.h b/engines/dragons/dragonini.h index 0766eb174be..8912aa2fdb7 100644 --- a/engines/dragons/dragonini.h +++ b/engines/dragons/dragonini.h @@ -65,11 +65,13 @@ struct DragonINI class DragonINIResource { private: + BigfileArchive *_bigfileArchive; DragonINI *_dragonINI; uint16 _count; DragonINI *_flickerINI; public: DragonINIResource(BigfileArchive *bigfileArchive); + void reset(); uint16 totalRecords() { return _count; } DragonINI *getRecord(uint16 index); void setFlickerRecord(DragonINI *dragonINI); diff --git a/engines/dragons/dragons.cpp b/engines/dragons/dragons.cpp index 9495689fb7d..37835d6a2e3 100644 --- a/engines/dragons/dragons.cpp +++ b/engines/dragons/dragons.cpp @@ -66,7 +66,6 @@ DragonsEngine::DragonsEngine(OSystem *syst) : Engine(syst) { run_func_ptr_unk_countdown_timer = 0; data_8006a3a0_flag = 0; data_800633fa = 0; - iniItemInHand = 0; _inventory = new Inventory(this); _cursor = new Cursor(this); @@ -141,8 +140,21 @@ Common::Error DragonsEngine::run() { _cursor->init(_actorManager, _dragonINIResource); _inventory->init(_actorManager, _backgroundResourceLoader, new Bag(_bigfileArchive, _screen), _dragonINIResource); + _dragonVAR->setVar(1, 1); + + _scene->setSceneId(2); + byte *obd = _dragonOBD->getObdAtOffset(0x2c5a); //TODO read value from dragon.spt + 0xc + ScriptOpCall scriptOpCall; + scriptOpCall._code = obd + 4; + scriptOpCall._codeEnd = scriptOpCall._code + READ_LE_UINT32(obd); + _scriptOpcodes->runScript(scriptOpCall); + uint16 sceneId = 0x12; - _dragonINIResource->getFlickerRecord()->sceneId = sceneId; //TODO + if(getINI(0)->sceneId == 0) { + getINI(0)->sceneId = sceneId; //TODO + } else { + _scene->setSceneId(getINI(0)->sceneId); + } _sceneId1 = sceneId; _scene->loadScene(sceneId, 0x1e); @@ -209,7 +221,6 @@ void DragonsEngine::gameLoop() actorId = 0; while(!shouldQuit()) { - LAB_80026a74: _scene->draw(); _screen->updateScreen(); wait(); @@ -290,7 +301,7 @@ void DragonsEngine::gameLoop() // actorId = CheckButtonMapPress_CycleUp(0); // if (((actorId & 0xffff) != 0) && isInputEnabled()) { // _cursor->_sequenceID = _cursor->_sequenceID + 1; -// if (iniItemInHand == 0) { +// if (_cursor->iniItemInHand == 0) { // bVar1 = _cursor->_sequenceID < 5; // } // else { @@ -359,7 +370,7 @@ void DragonsEngine::gameLoop() _inventory->setType(1); _inventory->openInventory(); joined_r0x80027a38: - if (iniItemInHand == 0) { + if (_cursor->iniItemInHand == 0) { _cursor->_sequenceID = 1; actorId = uVar3; } @@ -368,7 +379,7 @@ void DragonsEngine::gameLoop() actorId = uVar3; } } - goto LAB_80026a74; + continue; } uVar6 = _inventory->getType(); if (checkForActionButtonRelease() && isFlagSet(ENGINE_FLAG_8)) { @@ -377,7 +388,7 @@ void DragonsEngine::gameLoop() if (_cursor->_iniUnderCursor == 0x8002) { LAB_80027294: uVar7 = 0; - if (iniItemInHand == 0) { + if (_cursor->iniItemInHand == 0) { if ((bit_flags_8006fbd8 & 3) != 1) { sequenceId = _dragonVAR->getVar(7); uVar7 = _inventory->_old_showing_value; @@ -395,12 +406,12 @@ void DragonsEngine::gameLoop() if (uVar7 < 0x29) { _cursor->_sequenceID = 1; waitForFrames(1); - uVar6 = iniItemInHand; - iniItemInHand = 0; + uVar6 = _cursor->iniItemInHand; + _cursor->iniItemInHand = 0; _cursor->_iniUnderCursor = 0; unkArray_uint16[(uint)uVar7] = uVar6; actorId = uVar3; - goto LAB_80026a74; + continue; } } } @@ -413,7 +424,7 @@ void DragonsEngine::gameLoop() _inventory->_old_showing_value = uVar6; FUN_80038890(); actorId = uVar3; - goto LAB_80026a74; + continue; } } LAB_80027ab4: @@ -433,7 +444,7 @@ void DragonsEngine::gameLoop() clearFlags(ENGINE_FLAG_8); } _scriptOpcodes->_data_800728c0 = _cursor->data_80072890; - _cursor->data_80072890 = iniItemInHand; + _cursor->data_80072890 = _cursor->iniItemInHand; } } } @@ -456,7 +467,7 @@ void DragonsEngine::gameLoop() LAB_80027b58: runINIScripts(); actorId = uVar3; - goto LAB_80026a74; + continue; } if (checkForInventoryButtonRelease()) { _counter = 0; @@ -466,7 +477,7 @@ void DragonsEngine::gameLoop() _inventory->_old_showing_value = _inventory->getType(); actorId = uVar3; _inventory->setType(uVar6); - goto LAB_80026a74; + continue; } uVar6 = _inventory->getType(); if (checkForActionButtonRelease() && isFlagSet(ENGINE_FLAG_8)) { @@ -489,7 +500,7 @@ void DragonsEngine::gameLoop() } _inventory->_old_showing_value = uVar6; actorId = uVar3; - goto LAB_80026a74; + continue; } if (_cursor->_iniUnderCursor != 0) { actorId_00 = 0; @@ -497,7 +508,7 @@ void DragonsEngine::gameLoop() _cursor->data_800728b0_cursor_seqID = _cursor->_sequenceID; _cursor->data_80072890 = _cursor->_iniUnderCursor; if (4 < _cursor->_sequenceID) { - _cursor->data_80072890 = iniItemInHand; + _cursor->data_80072890 = _cursor->iniItemInHand; _scriptOpcodes->_data_800728c0 = _cursor->_iniUnderCursor; } clearFlags(ENGINE_FLAG_8); @@ -513,10 +524,10 @@ void DragonsEngine::gameLoop() } puVar9 = unkArray_uint16 + (actorId_00 & 0xffff); Actor *actor = _actorManager->getActor(actorId_00 + 0x17); - *puVar9 = iniItemInHand; + *puVar9 = _cursor->iniItemInHand; _cursor->data_8007283c = actor->_sequenceID; actor->clearFlag(ACTOR_FLAG_40); - iniItemInHand = _cursor->_iniUnderCursor; + _cursor->iniItemInHand = _cursor->_iniUnderCursor; _cursor->_sequenceID = 5; actorId = uVar3; if (*puVar9 != 0) { @@ -532,10 +543,10 @@ void DragonsEngine::gameLoop() actor->priorityLayer = 6; actorId = uVar3; } - goto LAB_80026a74; + continue; } uVar6 = 0; - if (iniItemInHand == 0) goto LAB_80027b58; + if (_cursor->iniItemInHand == 0) goto LAB_80027b58; //drop item back into inventory actorId = 0; do { @@ -551,12 +562,12 @@ void DragonsEngine::gameLoop() } while (uVar6 < 0x29); if (actorId != 0x29) { actorId_00 = (uint)(ushort)(uVar6 + 0x17); - unkArray_uint16[actorId] = iniItemInHand; + unkArray_uint16[actorId] = _cursor->iniItemInHand; Actor *actor = _actorManager->getActor(actorId_00); actor->flags = 0; actor->priorityLayer = 0; actor->field_e = 0x100; - iniItemInHand = 0; + _cursor->iniItemInHand = 0; actor->updateSequence( getINI((uint)unkArray_uint16[actorId] - 1)->field_8 * 2 + 10); uVar6 = _cursor->_sequenceID; @@ -571,7 +582,7 @@ void DragonsEngine::gameLoop() } } LAB_8002790c: - if ((iniItemInHand == 0) || + if ((_cursor->iniItemInHand == 0) || (((ushort)(_cursor->_x - 10U) < 300 && ((ushort)(_cursor->_y - 10U) < 0xb4)))) goto LAB_80027b58; _cursor->_sequenceID = 5; @@ -653,45 +664,6 @@ void DragonsEngine::updateHandler() { data_8006a3a0_flag &= ~0x40; } -const char *DragonsEngine::getSavegameFilename(int num) { - static Common::String filename; - filename = getSavegameFilename(_targetName, num); - return filename.c_str(); -} - -Common::String DragonsEngine::getSavegameFilename(const Common::String &target, int num) { - assert(num >= 0 && num <= 999); - return Common::String::format("%s.%03d", target.c_str(), num); -} - -#define DRAGONS_SAVEGAME_VERSION 0 - -kReadSaveHeaderError -DragonsEngine::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail) { - - header.version = in->readUint32LE(); - if (header.version > DRAGONS_SAVEGAME_VERSION) - return kRSHEInvalidVersion; - - byte descriptionLen = in->readByte(); - header.description = ""; - while (descriptionLen--) { - header.description += (char) in->readByte(); - } - - if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) { - return kRSHEIoError; - } - - header.flags = in->readUint32LE(); - - header.saveDate = in->readUint32LE(); - header.saveTime = in->readUint32LE(); - header.playTime = in->readUint32LE(); - - return ((in->eos() || in->err()) ? kRSHEIoError : kRSHENoError); -} - uint32 DragonsEngine::calulateTimeLeft() { uint32 now; @@ -1182,6 +1154,19 @@ void DragonsEngine::FUN_80038994() { } void DragonsEngine::FUN_8002931c() { + + DragonINI *flicker = _dragonINIResource->getFlickerRecord(); + if (flicker && flicker->actor) { + flicker->actor->clearFlag(ACTOR_FLAG_10); + if (getCurrentSceneId() != 0x2e || !flicker->actor->_actorResource || flicker->actor->_actorResource->_id != 0x91) { + flicker->actor->setFlag(ACTOR_FLAG_4); + } + } +//TODO +// uVar1 = FUN_80023830(9); +// local_30 = 0x11; +// local_2c = local_280[(uint)DAT_800728b0 * 9 + (uVar1 & 0xffff)]; +// FlickerTalkMaybe(&local_30); error("FUN_8002931c"); //TODO } @@ -1190,4 +1175,19 @@ void DragonsEngine::reset_screen_maybe() { //TODO } +bool DragonsEngine::canLoadGameStateCurrently() { + return isInputEnabled(); +} + +bool DragonsEngine::canSaveGameStateCurrently() { + return isInputEnabled() && _inventory->getType() != 1; +} + +bool DragonsEngine::hasFeature(Engine::EngineFeature f) const { + return + // TODO (f == kSupportsRTL) || + (f == kSupportsLoadingDuringRuntime) || + (f == kSupportsSavingDuringRuntime); +} + } // End of namespace Dragons diff --git a/engines/dragons/dragons.h b/engines/dragons/dragons.h index 6beac6fe515..22dd7b82160 100644 --- a/engines/dragons/dragons.h +++ b/engines/dragons/dragons.h @@ -127,7 +127,6 @@ public: uint16 data_800633fa; Inventory *_inventory; Cursor *_cursor; - uint16 iniItemInHand; uint16 unkArray_uint16[42]; opCode1AStruct opCode1A_tbl[8]; @@ -157,7 +156,8 @@ private: bool _leftMouseButtonUp; bool _rightMouseButtonUp; bool _iKeyUp; - +protected: + virtual bool hasFeature(EngineFeature f) const; public: DragonsEngine(OSystem *syst); ~DragonsEngine(); @@ -169,6 +169,11 @@ public: static Common::String getSavegameFilename(const Common::String &target, int num); static kReadSaveHeaderError readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail = true); + virtual Common::Error loadGameState(int slot); + virtual bool canLoadGameStateCurrently(); + virtual Common::Error saveGameState(int slot, const Common::String &desc); + virtual bool canSaveGameStateCurrently(); + void updateActorSequences(); void setFlags(uint32 flags); void clearFlags(uint32 flags); @@ -198,6 +203,8 @@ public: void reset_screen_maybe(); private: + bool savegame(const char *filename, const char *description); + bool loadgame(const char *filename); void gameLoop(); void updateHandler(); void updatePathfindingActors(); diff --git a/engines/dragons/dragonvar.cpp b/engines/dragons/dragonvar.cpp index 18df7730060..d35fe5b4549 100644 --- a/engines/dragons/dragonvar.cpp +++ b/engines/dragons/dragonvar.cpp @@ -24,16 +24,12 @@ namespace Dragons { -DragonVAR::DragonVAR(BigfileArchive *bigfileArchive) { - uint32 size; - _data = bigfileArchive->load("dragon.var", size); - assert(size == 30); +DragonVAR::DragonVAR(BigfileArchive *bigfileArchive): _bigfileArchive(bigfileArchive), _data(0) { + reset(); } DragonVAR::~DragonVAR() { - if (_data) { delete _data; - } } uint16 DragonVAR::getVar(uint16 offset) { @@ -48,4 +44,11 @@ void DragonVAR::setVar(uint16 offset, uint16 value) { WRITE_LE_INT16(_data + offset * 2, value); } +void DragonVAR::reset() { + delete _data; + uint32 size; + _data = _bigfileArchive->load("dragon.var", size); + assert(size == 30); +} + } // End of namespace Dragons diff --git a/engines/dragons/dragonvar.h b/engines/dragons/dragonvar.h index 46991c09c15..1ead7699d79 100644 --- a/engines/dragons/dragonvar.h +++ b/engines/dragons/dragonvar.h @@ -31,10 +31,12 @@ class BigfileArchive; class DragonVAR { private: byte *_data; + BigfileArchive *_bigfileArchive; public: virtual ~DragonVAR(); DragonVAR(BigfileArchive *bigfileArchive); + void reset(); uint16 getVar(uint16 offset); void setVar(uint16 offset, uint16 value); }; diff --git a/engines/dragons/saveload.cpp b/engines/dragons/saveload.cpp new file mode 100644 index 00000000000..d5eee02c26f --- /dev/null +++ b/engines/dragons/saveload.cpp @@ -0,0 +1,184 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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. + * + */ +#include "common/savefile.h" + +#include "graphics/thumbnail.h" + +#include "dragons.h" +#include "dragonflg.h" +#include "dragonini.h" +#include "dragonvar.h" +#include "scene.h" +#include "cursor.h" + + +namespace Dragons { + +#define ILLUSIONS_SAVEGAME_VERSION 0 + +Dragons::kReadSaveHeaderError DragonsEngine::readSaveHeader(Common::SeekableReadStream *in, SaveHeader &header, bool skipThumbnail) { + + header.version = in->readUint32LE(); + if (header.version > ILLUSIONS_SAVEGAME_VERSION) + return kRSHEInvalidVersion; + + byte descriptionLen = in->readByte(); + header.description = ""; + while (descriptionLen--) { + header.description += (char)in->readByte(); + } + + if (!Graphics::loadThumbnail(*in, header.thumbnail, skipThumbnail)) { + return kRSHEIoError; + } + + // Not used yet, reserved for future usage +// header.gameID = in->readByte(); + header.flags = in->readUint32LE(); + + header.saveDate = in->readUint32LE(); + header.saveTime = in->readUint32LE(); + header.playTime = in->readUint32LE(); + + return ((in->eos() || in->err()) ? kRSHEIoError : kRSHENoError); +} + +bool DragonsEngine::savegame(const char *filename, const char *description) { + + Common::OutSaveFile *out; + if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { + warning("Can't create file '%s', game not saved", filename); + return false; + } + + TimeDate curTime; + g_system->getTimeAndDate(curTime); + + // Header start + out->writeUint32LE(ILLUSIONS_SAVEGAME_VERSION); + + byte descriptionLen = strlen(description); + out->writeByte(descriptionLen); + out->write(description, descriptionLen); + + // TODO Probably pre-generate the thumbnail before the internal menu system is + // called to have a thumbnail without the menu system itself on it. + // Use the automatic thumbnail generation only when the ScummVM save dialog is used. + Graphics::saveThumbnail(*out); + + // Not used yet, reserved for future usage + //out->writeByte(0); + out->writeUint32LE(0); + uint32 saveDate = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); + uint32 saveTime = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); + uint32 playTime = g_engine->getTotalPlayTime() / 1000; + out->writeUint32LE(saveDate); + out->writeUint32LE(saveTime); + out->writeUint32LE(playTime); + // Header end + + //TODO save gamestate here. _gameState->write(out); + out->writeByte((int8)getCurrentSceneId()); + _dragonFLG->saveState(out); + + out->finalize(); + delete out; + return true; +} + +bool DragonsEngine::loadgame(const char *filename) { + Common::InSaveFile *in; + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + warning("Can't open file '%s', game not loaded", filename); + return false; + } + + SaveHeader header; + + kReadSaveHeaderError errorCode = readSaveHeader(in, header); + + if (errorCode != kRSHENoError) { + warning("Error loading savegame '%s'", filename); + delete in; + return false; + } + + g_engine->setTotalPlayTime(header.playTime * 1000); + + // TODO load game state here. _gameState->read(in); + uint16 newSceneId = (uint16)in->readByte(); + _dragonFLG->loadState(in); + _dragonFLG->set(165, false); + + _dragonVAR->reset(); + + _dragonVAR->setVar(1, 1); + + _dragonINIResource->reset(); + + _flags = 0x1046; + _flags &= 0x1c07040; + _flags |= 0x26; + _unkFlags1 = 0; + + _cursor->init(_actorManager, _dragonINIResource); +// _inventory->init(_actorManager, _backgroundResourceLoader, new Bag(_bigfileArchive, _screen), _dragonINIResource); + + if(getINI(0)->sceneId == 0) { + getINI(0)->sceneId = newSceneId; //TODO + } else { + _scene->setSceneId(getINI(0)->sceneId); + } + _sceneId1 = newSceneId; + + _scene->loadScene(newSceneId, 0x1e); //TODO + + delete in; + return true; +} + +Common::Error DragonsEngine::loadGameState(int slot) { + const char *fileName = getSavegameFilename(slot); + if (!loadgame(fileName)) + return Common::kReadingFailed; + return Common::kNoError; +} + +Common::Error DragonsEngine::saveGameState(int slot, const Common::String &description) { + const char *fileName = getSavegameFilename(slot); + if (!savegame(fileName, description.c_str())) + return Common::kWritingFailed; + return Common::kNoError; +} + +const char *DragonsEngine::getSavegameFilename(int num) { + static Common::String filename; + filename = getSavegameFilename(_targetName, num); + return filename.c_str(); +} + +Common::String DragonsEngine::getSavegameFilename(const Common::String &target, int num) { + assert(num >= 0 && num <= 999); + return Common::String::format("%s.%03d", target.c_str(), num); +} + +} // End of namespace Illusions diff --git a/engines/dragons/scriptopcodes.cpp b/engines/dragons/scriptopcodes.cpp index 15a56e839b3..71b7b115238 100644 --- a/engines/dragons/scriptopcodes.cpp +++ b/engines/dragons/scriptopcodes.cpp @@ -999,14 +999,14 @@ void ScriptOpcodes::opCode_Unk7(ScriptOpCall &scriptOpCall) { } if (sceneId == 1) { - if (_vm->iniItemInHand != 0) { + if (_vm->_cursor->iniItemInHand != 0) { uint16 freeSlot = 0; for( ;_vm->unkArray_uint16[freeSlot] != 0; freeSlot++) { if (_vm->unkArray_uint16[freeSlot] == 0) { break; } } - _vm->unkArray_uint16[freeSlot] = _vm->iniItemInHand; + _vm->unkArray_uint16[freeSlot] = _vm->_cursor->iniItemInHand; if (_vm->_inventory->getType() == 1) { Actor *actor = _vm->_actorManager->getActor(freeSlot + 0x17); actor->flags = 0; @@ -1026,7 +1026,7 @@ void ScriptOpcodes::opCode_Unk7(ScriptOpCall &scriptOpCall) { _vm->_cursor->data_800728b0_cursor_seqID = 5; _vm->_cursor->_sequenceID = 5; _vm->_cursor->data_8007283c = _vm->getINI(field2 - 1)->field_8 * 2 + 10; - _vm->iniItemInHand = field2; + _vm->_cursor->iniItemInHand = field2; } } ini->sceneId = sceneId; diff --git a/engines/dragons/specialopcodes.cpp b/engines/dragons/specialopcodes.cpp index 02e2f5b1a4a..aff0cb8b135 100644 --- a/engines/dragons/specialopcodes.cpp +++ b/engines/dragons/specialopcodes.cpp @@ -82,6 +82,9 @@ void SpecialOpcodes::initOpcodes() { OPCODE(0x5e, spcUnk5e); OPCODE(0x5f, spcUnk5f); + + OPCODE(0x7b, spcSetCameraXToZero); + } #undef OPCODE @@ -192,4 +195,8 @@ void SpecialOpcodes::panCamera(int16 mode) { return; } +void SpecialOpcodes::spcSetCameraXToZero() { + _vm->_scene->_camera.x = 0; +} + } // End of namespace Dragons diff --git a/engines/dragons/specialopcodes.h b/engines/dragons/specialopcodes.h index 1c549954c23..9c348a2940a 100644 --- a/engines/dragons/specialopcodes.h +++ b/engines/dragons/specialopcodes.h @@ -68,6 +68,7 @@ protected: void spcUnk5e(); void spcUnk5f(); + void spcSetCameraXToZero(); //0x7b private: void panCamera(int16 mode); };