From df14027c411af320ab6a696f37cbc47e35675393 Mon Sep 17 00:00:00 2001 From: Robert Špalek Date: Sun, 4 Oct 2009 05:44:23 +0000 Subject: Implemented rudimentary game loading/saving. Fixed many bugs in the boilerplate. Saving (only) things that really need to be saved. Loading seems to work modulo dialogs and (possibly) inventory. svn-id: r44586 --- engines/draci/draci.cpp | 19 +++++++++++++++---- engines/draci/game.cpp | 31 +++++++++++++++++++++++++++++++ engines/draci/game.h | 4 ++++ engines/draci/mouse.cpp | 1 + engines/draci/saveload.cpp | 26 +++++++++++++------------- engines/draci/saveload.h | 4 ++-- 6 files changed, 66 insertions(+), 19 deletions(-) diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index 9ecbfb37bb..70e19d1dd1 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -41,6 +41,7 @@ #include "draci/sprite.h" #include "draci/screen.h" #include "draci/mouse.h" +#include "draci/saveload.h" namespace Draci { @@ -350,8 +351,19 @@ const char *DraciEngine::getSavegameFile(int saveGameIdx) { } Common::Error DraciEngine::loadGameState(int slot) { - // TODO - return Common::kNoError; + // When called from run() using save_slot, the next operation is the + // call to start() calling enterNewRoom(). + // When called from handleEvents() in the middle of the game, the next + // operation after handleEvents() exits from loop(), and returns to + // start() to the same place as above. + // In both cases, we are safe to override the data structures right + // here are now, without waiting for any other code to finish, thanks + // to our constraint in canLoadGameStateCurrently() and to having + // enterNewRoom() called right after we exit from here. + // + // TODO: Handle saving in the map room. Verify inventory and fix + // dialogs. + return loadSavegameData(slot, this); } bool DraciEngine::canLoadGameStateCurrently() { @@ -360,8 +372,7 @@ bool DraciEngine::canLoadGameStateCurrently() { } Common::Error DraciEngine::saveGameState(int slot, const char *desc) { - // TODO - return Common::kNoError; + return saveSavegameData(slot, desc, *this); } bool DraciEngine::canSaveGameStateCurrently() { diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 5d3c6a3384..297214d8b2 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -226,6 +226,8 @@ void Game::loop() { _loopStatus, _loopSubstatus); _vm->handleEvents(); + if (shouldExitLoop()) // after loading + break; // Fetch mouse coordinates int x = _vm->_mouse->getPosX(); @@ -1384,6 +1386,10 @@ int Game::getRoomNum() const { return _currentRoom._roomNum; } +void Game::setRoomNum(int num) { + _currentRoom._roomNum = num; +} + int Game::getPreviousRoomNum() const { return _previousRoom; } @@ -1502,6 +1508,31 @@ Game::~Game() { delete[] _items; } +void Game::DoSync(Common::Serializer &s) { + s.syncAsUint16LE(_currentRoom._roomNum); + + for (uint i = 0; i < _info._numObjects; ++i) { + GameObject& obj = _objects[i]; + s.syncAsSint16LE(obj._location); + s.syncAsByte(obj._visible); + } + + for (uint i = 0; i < _info._numItems; ++i) { + s.syncAsByte(_itemStatus[i]); + } + + for (int i = 0; i < kInventorySlots; ++i) { + s.syncAsSint16LE(_inventory[i]); + } + + for (int i = 0; i < _info._numVariables; ++i) { + s.syncAsSint16LE(_variables[i]); + } + for (uint i = 0; i < _info._numDialogueBlocks; ++i) { + s.syncAsSint16LE(_dialogueVars[i]); + } + +} bool WalkingMap::isWalkable(int x, int y) const { // Convert to map pixels diff --git a/engines/draci/game.h b/engines/draci/game.h index 9766e9a863..3687c3d2de 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -27,6 +27,7 @@ #define DRACI_GAME_H #include "common/str.h" +#include "common/serializer.h" #include "draci/barchive.h" #include "draci/script.h" #include "draci/animation.h" @@ -275,6 +276,7 @@ public: const Person *getPerson(int personID) const; int getRoomNum() const; + void setRoomNum(int num); int getPreviousRoomNum() const; void scheduleEnteringRoomUsingGate(int room, int gate); @@ -336,6 +338,8 @@ public: void schedulePalette(int paletteID); int getScheduledPalette() const; + void DoSync(Common::Serializer &s); + private: void deleteAnimationsAfterIndex(int lastAnimIndex); void enterNewRoom(); diff --git a/engines/draci/mouse.cpp b/engines/draci/mouse.cpp index 69943faa3c..2d30f1f21f 100644 --- a/engines/draci/mouse.cpp +++ b/engines/draci/mouse.cpp @@ -42,6 +42,7 @@ Mouse::Mouse(DraciEngine *vm) { void Mouse::handleEvent(Common::Event event) { switch (event.type) { case Common::EVENT_LBUTTONDOWN: + // TODO: remove _modifierState, since right click can be achieved via Cmd if (!(_modifierState & 3)) { debugC(6, kDraciGeneralDebugLevel, "Left button down (x: %u y: %u)", _x, _y); _lButton = true; diff --git a/engines/draci/saveload.cpp b/engines/draci/saveload.cpp index bd2f247dd4..89516d2ba2 100644 --- a/engines/draci/saveload.cpp +++ b/engines/draci/saveload.cpp @@ -72,7 +72,7 @@ bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header) { return true; } -void writeSavegameHeader(Common::OutSaveFile *out, const DraciSavegameHeader &header, const Graphics::Surface &thumb) { +void writeSavegameHeader(Common::OutSaveFile *out, const DraciSavegameHeader &header) { // Write out a savegame header out->write(draciIdentString, 6); out->writeByte(DRACI_SAVEGAME_VERSION); @@ -80,19 +80,15 @@ void writeSavegameHeader(Common::OutSaveFile *out, const DraciSavegameHeader &he // Write savegame name out->write(header.saveName.c_str(), header.saveName.size() + 1); - out->writeUint32BE(header.date); - out->writeUint16BE(header.time); - out->writeUint32BE(header.playtime); + out->writeUint32LE(header.date); + out->writeUint16LE(header.time); + out->writeUint32LE(header.playtime); // Create a thumbnail and save it - Graphics::saveThumbnail(*out, thumb); + Graphics::saveThumbnail(*out); } -static void DoSync(Common::Serializer &s) { -} - - -Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, const DraciEngine &vm) { +Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, DraciEngine &vm) { const char *filename = vm.getSavegameFile(saveGameIdx); Common::SaveFileManager *saveMan = g_system->getSavefileManager(); Common::OutSaveFile *f = saveMan->openForSaving(filename); @@ -108,7 +104,7 @@ Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, header.date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); header.time = ((curTime.tm_hour & 0xFF) << 8) | ((curTime.tm_min) & 0xFF); header.playtime = vm._system->getMillis() / 1000 - vm._engineStartTime; - writeSavegameHeader(f, header, *vm._screen->getSurface()); + writeSavegameHeader(f, header); if (f->err()) { delete f; @@ -117,7 +113,7 @@ Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, } else { // Create the remainder of the savegame Common::Serializer s(NULL, f); - DoSync(s); + vm._game->DoSync(s); f->finalize(); delete f; @@ -142,12 +138,16 @@ Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm) { // Synchronise the remaining data of the savegame Common::Serializer s(f, NULL); - DoSync(s); + int oldRoomNum = vm->_game->getRoomNum(); + vm->_game->DoSync(s); delete f; // Post processing vm->_engineStartTime = vm->_system->getMillis() / 1000 - header.playtime; + vm->_game->scheduleEnteringRoomUsingGate(vm->_game->getRoomNum(), 0); + vm->_game->setRoomNum(oldRoomNum); + vm->_game->setExitLoop(true); return Common::kNoError; } diff --git a/engines/draci/saveload.h b/engines/draci/saveload.h index b6a6c2930e..0103d6b5ae 100644 --- a/engines/draci/saveload.h +++ b/engines/draci/saveload.h @@ -46,8 +46,8 @@ struct DraciSavegameHeader { class DraciEngine; bool readSavegameHeader(Common::InSaveFile *in, DraciSavegameHeader &header); -void writeSavegameHeader(Common::OutSaveFile *out, const DraciSavegameHeader &header, const Graphics::Surface &thumb); -Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, const DraciEngine &vm); +void writeSavegameHeader(Common::OutSaveFile *out, const DraciSavegameHeader &header); +Common::Error saveSavegameData(int saveGameIdx, const Common::String &saveName, DraciEngine &vm); Common::Error loadSavegameData(int saveGameIdx, DraciEngine *vm); } // End of namespace Draci -- cgit v1.2.3