diff options
author | Paul Gilbert | 2006-10-02 12:48:56 +0000 |
---|---|---|
committer | Paul Gilbert | 2006-10-02 12:48:56 +0000 |
commit | 1a96e26bf6bd9593da746e1cf3da98448df3a92d (patch) | |
tree | b93ffac36b281447d64e08ce3d34a4511f4b6a89 | |
parent | e8623fa477119e4b418200826e1bac372b9f8df4 (diff) | |
download | scummvm-rg350-1a96e26bf6bd9593da746e1cf3da98448df3a92d.tar.gz scummvm-rg350-1a96e26bf6bd9593da746e1cf3da98448df3a92d.tar.bz2 scummvm-rg350-1a96e26bf6bd9593da746e1cf3da98448df3a92d.zip |
Added functionality to allow saving/loading the game state
svn-id: r24070
-rw-r--r-- | engines/lure/game.cpp | 10 | ||||
-rw-r--r-- | engines/lure/hotspots.cpp | 250 | ||||
-rw-r--r-- | engines/lure/hotspots.h | 21 | ||||
-rw-r--r-- | engines/lure/lure.cpp | 107 | ||||
-rw-r--r-- | engines/lure/lure.h | 7 | ||||
-rw-r--r-- | engines/lure/luredefs.h | 1 | ||||
-rw-r--r-- | engines/lure/menu.cpp | 4 | ||||
-rw-r--r-- | engines/lure/res.cpp | 19 | ||||
-rw-r--r-- | engines/lure/res.h | 3 | ||||
-rw-r--r-- | engines/lure/res_struct.cpp | 138 | ||||
-rw-r--r-- | engines/lure/res_struct.h | 12 | ||||
-rw-r--r-- | engines/lure/room.cpp | 20 | ||||
-rw-r--r-- | engines/lure/room.h | 2 |
13 files changed, 581 insertions, 13 deletions
diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp index 1623973031..a7be42487a 100644 --- a/engines/lure/game.cpp +++ b/engines/lure/game.cpp @@ -58,7 +58,7 @@ void Game::nextFrame() { res.pausedList().countdown(); room.checkCursor(); room.update(); - + // Call the tick method for each hotspot - this is somewaht complicated // by the fact that a tick proc can unload both itself and/or others, // so we first get a list of the Ids, and call the tick proc for each @@ -71,6 +71,7 @@ void Game::nextFrame() { idList[idSize++] = hotspot->hotspotId(); } + debugC(ERROR_DETAILED, kLureDebugAnimations, "Hotspot ticks begin"); for (int idCtr = 0; idCtr < idSize; ++idCtr) { Hotspot *hotspot = res.getActiveHotspot(idList[idCtr]); if (hotspot) { @@ -78,6 +79,7 @@ void Game::nextFrame() { hotspot->tick(); } } + debugC(ERROR_DETAILED, kLureDebugAnimations, "Hotspot ticks end"); delete[] idList; Screen::getReference().update(); @@ -119,6 +121,7 @@ void Game::execute() { timerVal = system.getMillis(); nextFrame(); } + res.delayList().tick(); while (events.pollEvent()) { @@ -227,12 +230,11 @@ void Game::handleMenuResponse(uint8 selection) { break; case MENUITEM_SAVE_GAME: - if (SaveRestoreDialog::show(true, filename)) { - // Save the game here - } + SaveRestoreDialog::show(true); break; case MENUITEM_RESTORE_GAME: + SaveRestoreDialog::show(false); break; case MENUITEM_QUIT: diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp index 7b94d6391e..32a111a97d 100644 --- a/engines/lure/hotspots.cpp +++ b/engines/lure/hotspots.cpp @@ -45,6 +45,7 @@ Hotspot::Hotspot(HotspotData *res): _pathFinder(this) { _persistant = false; _hotspotId = res->hotspotId; + _originalId = res->hotspotId; _roomNumber = res->roomNumber; _startX = res->startX; _startY = res->startY; @@ -67,9 +68,7 @@ Hotspot::Hotspot(HotspotData *res): _pathFinder(this) { _colourOffset = res->colourOffset; _override = resources.getHotspotOverride(res->hotspotId); - - if (_data->animRecordId != 0) - setAnimation(_data->animRecordId); + setAnimation(_data->animRecordId); _tickHandler = HotspotTickHandlers::getHandler(_data->tickProcOffset); _frameCtr = 0; @@ -90,6 +89,8 @@ Hotspot::Hotspot(HotspotData *res): _pathFinder(this) { // Special constructor used to create a voice hotspot Hotspot::Hotspot(Hotspot *character, uint16 objType): _pathFinder(this) { + assert(character); + _originalId = objType; _data = NULL; _anim = NULL; _frames = NULL; @@ -130,6 +131,8 @@ Hotspot::Hotspot(Hotspot *character, uint16 objType): _pathFinder(this) { case EXCLAMATION_ANIM_ID: _roomNumber = character->roomNumber(); _hotspotId = 0xfffe; + _startX = character->x() + character->talkX() + 12; + _startY = character->y() + character->talkY() - 20; _width = 32; _height = 18; _widthCopy = 19; @@ -162,6 +165,7 @@ Hotspot::~Hotspot() { void Hotspot::setAnimation(uint16 newAnimId) { Resources &r = Resources::getReference(); HotspotAnimData *tempAnim; + _animId = newAnimId; if (newAnimId == 0) tempAnim = NULL; else tempAnim = r.getAnimation(newAnimId); @@ -1826,6 +1830,76 @@ void Hotspot::startTalk(HotspotData *charHotspot, uint16 id) { charHotspot->hotspotId, id); } +void Hotspot::saveToStream(Common::WriteStream *stream) { + _currentActions.saveToStream(stream); + _pathFinder.saveToStream(stream); + + stream->writeUint16LE(_roomNumber); + stream->writeSint16LE(_startX); + stream->writeSint16LE(_startY); + stream->writeSint16LE(_destX); + stream->writeSint16LE(_destY); + stream->writeUint16LE(_frameWidth); + stream->writeUint16LE(_height); + stream->writeUint16LE(_width); + stream->writeUint16LE(_heightCopy); + stream->writeUint16LE(_widthCopy); + stream->writeUint16LE(_yCorrection); + stream->writeUint16LE(_talkX); + stream->writeUint16LE(_talkY); + stream->writeByte(_layer); + stream->writeUint16LE(_sequenceOffset); + stream->writeUint16LE(_tickCtr); + stream->writeUint32LE(_actions); + stream->writeByte(_colourOffset); + stream->writeUint16LE(_animId); + stream->writeUint16LE(_frameNumber); + + stream->writeUint16LE(_frameCtr); + stream->writeByte(_skipFlag); + stream->writeUint16LE(_charRectY); + stream->writeUint16LE(_voiceCtr); + stream->writeUint16LE(_blockedOffset); + stream->writeUint16LE(_exitCtr); + stream->writeByte(_walkFlag); + stream->writeUint16LE(_startRoomNumber); +} + +void Hotspot::loadFromStream(Common::ReadStream *stream) { + _currentActions.loadFromStream(stream); + _pathFinder.loadFromStream(stream); + + _roomNumber = stream->readUint16LE(); + _startX = stream->readSint16LE(); + _startY = stream->readSint16LE(); + _destX = stream->readSint16LE(); + _destY = stream->readSint16LE(); + _frameWidth = stream->readUint16LE(); + _height = stream->readUint16LE(); + _width = stream->readUint16LE(); + _heightCopy = stream->readUint16LE(); + _widthCopy = stream->readUint16LE(); + _yCorrection = stream->readUint16LE(); + _talkX = stream->readUint16LE(); + _talkY = stream->readUint16LE(); + _layer = stream->readByte(); + _sequenceOffset = stream->readUint16LE(); + _tickCtr = stream->readUint16LE(); + _actions = stream->readUint32LE(); + _colourOffset = stream->readByte(); + setAnimation(stream->readUint16LE()); + setFrameNumber(stream->readUint16LE()); + + _frameCtr = stream->readUint16LE(); + _skipFlag = stream->readByte() != 0; + _charRectY = stream->readUint16LE(); + _voiceCtr = stream->readUint16LE(); + _blockedOffset = stream->readUint16LE(); + _exitCtr = stream->readUint16LE(); + _walkFlag = stream->readByte() != 0; + _startRoomNumber = stream->readUint16LE(); +} + /*------------------------------------------------------------------------*/ HandlerMethodPtr HotspotTickHandlers::getHandler(uint16 procOffset) { @@ -3313,6 +3387,34 @@ void PathFinder::initVars() { _countdownCtr -= 700; } +void PathFinder::saveToStream(Common::WriteStream *stream) { + // Note: current saving process only handles the PathFinder correctly + // if all pathfinding is done in one go (ie. multiple calls pathfinding + // isn't supported) + + ManagedList<WalkingActionEntry *>::iterator i; + for (i = _list.begin(); i != _list.end(); ++i) { + WalkingActionEntry *entry = *i; + stream->writeByte(entry->direction()); + stream->writeSint16LE(entry->rawSteps()); + } + stream->writeByte(0xff); + stream->writeByte(_result); + stream->writeSint16LE(_stepCtr); +} + +void PathFinder::loadFromStream(Common::ReadStream *stream) { + _inProgress = false; + _list.clear(); + uint8 direction; + while ((direction = stream->readByte()) != 0xff) { + int steps = stream->readSint16LE(); + _list.push_back(new WalkingActionEntry((Direction) direction, steps)); + } + _result = (PathFinderResult)stream->readByte(); + _stepCtr = stream->readSint16LE(); +} + // Current action entry class methods CurrentActionEntry::CurrentActionEntry(CurrentAction newAction, uint16 roomNum) { @@ -3345,6 +3447,75 @@ void CurrentActionEntry::setSupportData(uint16 entryId) { setSupportData(newEntry); } +void CurrentActionEntry::saveToStream(WriteStream *stream) { + debugC(ERROR_DETAILED, kLureDebugAnimations, "Saving hotspot action entry dyn=%d id=%d", + hasSupportData(), hasSupportData() ? supportData().id() : 0); + stream->writeByte((uint8) _action); + stream->writeUint16LE(_roomNumber); + stream->writeByte(hasSupportData()); + if (hasSupportData()) { + // Handle the support data + stream->writeByte(_dynamicSupportData); + if (_dynamicSupportData) + { + // Write out the dynamic data + stream->writeSint16LE(supportData().numParams()); + for (int index = 0; index < supportData().numParams(); ++index) + stream->writeUint16LE(supportData().param(index)); + } + else + { + // Write out the Id for the static entry + stream->writeSint16LE(supportData().id()); + } + } + debugC(ERROR_DETAILED, kLureDebugAnimations, "Finished saving hotspot action entry"); +} + +CurrentActionEntry *CurrentActionEntry::loadFromStream(ReadStream *stream) { + Resources &res = Resources::getReference(); + uint8 actionNum = stream->readByte(); + if (actionNum == 0xff) return NULL; + CurrentActionEntry *result; + + uint16 roomNumber = stream->readUint16LE(); + bool hasSupportData = stream->readByte() != 0; + + if (!hasSupportData) { + // An entry that doesn't have support data + result = new CurrentActionEntry( + (CurrentAction) actionNum, roomNumber); + } else { + // Handle support data for the entry + bool dynamicData = stream->readByte() != 0; + if (dynamicData) + { + // Load action entry that has dynamic data + result = new CurrentActionEntry( + (CurrentAction) actionNum, roomNumber); + result->_supportData = new CharacterScheduleEntry(); + Action action = (Action) stream->readByte(); + int numParams = stream->readSint16LE(); + uint16 *paramList = new uint16[numParams]; + for (int index = 0; index < numParams; ++index) + paramList[index] = stream->readUint16LE(); + + result->_supportData->setDetails2(action, numParams, paramList); + delete paramList; + } + else + { + // Load action entry with an NPC schedule entry + uint16 entryId = stream->readUint16LE(); + CharacterScheduleEntry *entry = res.charSchedules().getEntry(entryId); + result = new CurrentActionEntry((CurrentAction) actionNum, roomNumber); + result->setSupportData(entry); + } + } + + return result; +} + void CurrentActionStack::list(char *buffer) { ManagedList<CurrentActionEntry *>::iterator i; @@ -3409,6 +3580,31 @@ void CurrentActionStack::list(char *buffer) { } } +void CurrentActionStack::saveToStream(WriteStream *stream) { + ManagedList<CurrentActionEntry *>::iterator i; + + debugC(ERROR_DETAILED, kLureDebugAnimations, "Saving hotspot action stack"); + char buffer[MAX_DESC_SIZE]; + list(buffer); + debugC(ERROR_DETAILED, kLureDebugAnimations, "%s", buffer); + + for (i = _actions.begin(); i != _actions.end(); ++i) + { + CurrentActionEntry *rec = *i; + rec->saveToStream(stream); + } + stream->writeByte(0xff); // End of list marker + debugC(ERROR_DETAILED, kLureDebugAnimations, "Finished saving hotspot action stack"); +} + +void CurrentActionStack::loadFromStream(ReadStream *stream) { + CurrentActionEntry *rec; + + _actions.clear(); + while ((rec = CurrentActionEntry::loadFromStream(stream)) != NULL) + _actions.push_back(rec); +} + /*-------------------------------------------------------------------------*/ /* Support methods */ /* */ @@ -3548,5 +3744,53 @@ bool Support::isCharacterInList(uint16 *lst, int numEntries, uint16 charId) { return false; } +void HotspotList::saveToStream(WriteStream *stream) { + HotspotList::iterator i; + for (i = begin(); i != end(); ++i) + { + Hotspot *hotspot = *i; + debugC(ERROR_INTERMEDIATE, kLureDebugAnimations, "Saving hotspot %xh", hotspot->hotspotId()); + bool dynamicObject = hotspot->hotspotId() != hotspot->originalId(); + stream->writeUint16LE(hotspot->originalId()); + stream->writeByte(dynamicObject); + stream->writeUint16LE(hotspot->destHotspotId()); + hotspot->saveToStream(stream); + + debugC(ERROR_DETAILED, kLureDebugAnimations, "Saved hotspot %xh", hotspot->hotspotId()); + } + stream->writeUint16LE(0); +} + +void HotspotList::loadFromStream(ReadStream *stream) { + Resources &res = Resources::getReference(); + Hotspot *hotspot; + + clear(); + uint16 hotspotId = stream->readUint16LE(); + while (hotspotId != 0) + { + debugC(ERROR_INTERMEDIATE, kLureDebugAnimations, "Loading hotspot %xh", hotspotId); + bool dynamicObject = stream->readByte() != 0; + uint16 destHotspotId = stream->readUint16LE(); + + if (dynamicObject) { + // Add in a dynamic object (such as a floating talk bubble) + Hotspot *destHotspot = res.getActiveHotspot(destHotspotId); + assert(destHotspot); + hotspot = new Hotspot(destHotspot, hotspotId); + res.addHotspot(hotspot); + } + else + { + hotspot = res.activateHotspot(hotspotId); + } + assert(hotspot); + + hotspot->loadFromStream(stream); + debugC(ERROR_DETAILED, kLureDebugAnimations, "Loaded hotspot %xh", hotspotId); + + hotspotId = stream->readUint16LE(); + } +} } // end of namespace Lure diff --git a/engines/lure/hotspots.h b/engines/lure/hotspots.h index e58567e778..6cdb75f2a8 100644 --- a/engines/lure/hotspots.h +++ b/engines/lure/hotspots.h @@ -103,6 +103,9 @@ public: void setRoomNumber(uint16 roomNum) { _roomNumber = roomNum; } void setSupportData(CharacterScheduleEntry *newRec) { _supportData = newRec; } void setSupportData(uint16 entryId); + + void saveToStream(WriteStream *stream); + static CurrentActionEntry *loadFromStream(ReadStream *stream); }; class CurrentActionStack { @@ -138,6 +141,9 @@ public: void addFront(Action newAction, uint16 roomNum, uint16 param1, uint16 param2) { _actions.push_front(new CurrentActionEntry(newAction, roomNum, param1, param2)); } + + void saveToStream(WriteStream *stream); + void loadFromStream(ReadStream *stream); }; class WalkingActionEntry { @@ -197,6 +203,9 @@ public: bool isEmpty() { return _list.empty(); } int &stepCtr() { return _stepCtr; } PathFinderResult result() { return _result; } + + void saveToStream(Common::WriteStream *stream); + void loadFromStream(Common::ReadStream *stream); }; enum HotspotPrecheckResult {PC_EXECUTE, PC_NOT_IN_ROOM, PC_UNKNOWN, PC_INITIAL, PC_EXCESS}; @@ -206,10 +215,12 @@ enum HotspotPrecheckResult {PC_EXECUTE, PC_NOT_IN_ROOM, PC_UNKNOWN, PC_INITIAL, class Hotspot { private: HotspotData *_data; + uint16 _animId; HotspotAnimData *_anim; HandlerMethodPtr _tickHandler; Surface *_frames; uint16 _hotspotId; + uint16 _originalId; uint16 _roomNumber; int16 _startX, _startY; uint16 _height, _width; @@ -298,6 +309,7 @@ public: void setAnimation(uint16 newAnimId); void setAnimation(HotspotAnimData *newRecord); uint16 hotspotId() { return _hotspotId; } + uint16 originalId() { return _originalId; } Surface &frames() { return *_frames; } HotspotAnimData &anim() { return *_anim; } HotspotData *resource() { return _data; } @@ -465,9 +477,16 @@ public: void showMessage(uint16 messageId, uint16 destCharacterId = NOONE_ID); void scheduleConverse(uint16 destHotspot, uint16 messageId); void handleTalkDialog(); + + void saveToStream(Common::WriteStream *stream); + void loadFromStream(Common::ReadStream *stream); }; -typedef ManagedList<Hotspot *> HotspotList; +class HotspotList: public ManagedList<Hotspot *> { +public: + void saveToStream(WriteStream *stream); + void loadFromStream(ReadStream *stream); +}; } // End of namespace Lure diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp index deba78b698..8a65861e0f 100644 --- a/engines/lure/lure.cpp +++ b/engines/lure/lure.cpp @@ -30,6 +30,8 @@ #include "common/fs.h" #include "common/system.h" #include "common/md5.h" +#include "common/savefile.h" +#include "common/stream.h" #include "sound/mixer.h" #include "sound/mididrv.h" @@ -163,6 +165,8 @@ REGISTER_PLUGIN(LURE, "Lure of the Temptress Engine", "Lure of the Temptress (C) namespace Lure { +static LureEngine *int_engine = NULL; + LureEngine::LureEngine(OSystem *system): Engine(system) { Common::addSpecialDebugLevel(kLureDebugScripts, "scripts", "Scripts debugging"); @@ -241,6 +245,7 @@ void LureEngine::detectGame() { if (strcmp(g->md5sum, (char *)md5str) == 0) { _features = g->features; _game = g->id; + _language = g->language; if (g->description) g_system->setWindowCaption(g->description); @@ -274,6 +279,7 @@ int LureEngine::init() { _menu = new Menu(); Surface::initialise(); _room = new Room(); + int_engine = this; return 0; } @@ -294,6 +300,10 @@ LureEngine::~LureEngine() { delete _sys; } +LureEngine &LureEngine::getReference() { + return *int_engine; +} + int LureEngine::go() { if (ConfMan.getInt("boot_param") == 0) { // Show the introduction @@ -318,4 +328,101 @@ void LureEngine::quitGame() { _system->quit(); } +const char *LureEngine::generateSaveName(int slotNumber) { + static char buffer[15]; + + sprintf(buffer, "lure.%.3d", slotNumber); + return buffer; +} + +bool LureEngine::saveGame(uint8 slotNumber, Common::String &caption) { + Common::WriteStream *f = this->_saveFileMan->openForSaving( + generateSaveName(slotNumber)); + if (f == NULL) { + warning("saveGame: Failed to save slot %d", slotNumber); + return false; + } + + f->write("lure", 5); + f->writeByte(_language); + f->writeByte(LURE_DAT_MINOR); + f->writeString(caption); + f->writeByte(0); // End of string terminator + + Room::getReference().saveToStream(f); + Resources::getReference().saveToStream(f); + + delete f; + return true; +} + +#define FAILED_MSG "loadGame: Failed to load slot %d" + +bool LureEngine::loadGame(uint8 slotNumber) { + Common::ReadStream *f = this->_saveFileMan->openForLoading( + generateSaveName(slotNumber)); + if (f == NULL) { + warning(FAILED_MSG, slotNumber); + return false; + } + + // Check for header + char buffer[5]; + f->read(buffer, 5); + if (memcmp(buffer, "lure", 5) != 0) + { + warning(FAILED_MSG, slotNumber); + delete f; + return false; + } + + // Check language version + uint8 language = f->readByte(); + uint8 version = f->readByte(); + if ((language != _language) || (version != LURE_DAT_MINOR)) + { + warning("loadGame: Failed to load slot %d - incorrect version", slotNumber); + delete f; + return false; + } + + // Read in and discard the savegame caption + while (f->readByte() != 0) ; + + // Load in the data + Room::getReference().loadFromStream(f); + Resources::getReference().loadFromStream(f); + + delete f; + return true; +} + +Common::String *LureEngine::detectSave(int slotNumber) { + Common::ReadStream *f = this->_saveFileMan->openForLoading( + generateSaveName(slotNumber)); + if (f == NULL) return NULL; + Common::String *result = NULL; + + // Check for header + char buffer[5]; + f->read(&buffer[0], 5); + if (memcmp(&buffer[0], "lure", 5) == 0) { + // Check language version + uint8 language = f->readByte(); + uint8 version = f->readByte(); + if ((language == _language) && (version == LURE_DAT_MINOR)) { + // Read in the savegame title + char saveName[MAX_DESC_SIZE]; + char *p = saveName; + int decCtr = MAX_DESC_SIZE - 1; + while ((decCtr > 0) && ((*p++ = f->readByte()) != 0)) --decCtr; + *p = '\0'; + result = new Common::String(saveName); + } + } + + delete f; + return result; +} + } // End of namespace Lure diff --git a/engines/lure/lure.h b/engines/lure/lure.h index ec72205264..814fc8bfb7 100644 --- a/engines/lure/lure.h +++ b/engines/lure/lure.h @@ -43,6 +43,7 @@ class LureEngine : public Engine { private: uint32 _features; uint8 _game; + Common::Language _language; Disk *_disk; Resources *_resources; Screen *_screen; @@ -54,9 +55,11 @@ private: Room *_room; void detectGame(); + const char *generateSaveName(int slotNumber); public: LureEngine(OSystem *system); ~LureEngine(); + static LureEngine &getReference(); virtual int init(); virtual int go(); @@ -65,6 +68,10 @@ public: uint32 features() { return _features; } uint8 game() { return _game; } Disk &disk() { return *_disk; } + + bool loadGame(uint8 slotNumber); + bool saveGame(uint8 slotNumber, Common::String &caption); + Common::String *detectSave(int slotNumber); }; } // End of namespace Lure diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h index 358deaf03a..1462d9e94e 100644 --- a/engines/lure/luredefs.h +++ b/engines/lure/luredefs.h @@ -249,6 +249,7 @@ enum Action { #define CONVERSE_COUNTDOWN_SIZE 40 #define IDLE_COUNTDOWN_SIZE 15 #define MAX_TELL_COMMANDS 8 +#define MAX_SAVEGAME_SLOTS 10 // Countdown for # operations in path finder before breaking until next // tick - set it to 0 if you'd like all pathfinding to be done at once diff --git a/engines/lure/menu.cpp b/engines/lure/menu.cpp index da53e898fd..72ce50389e 100644 --- a/engines/lure/menu.cpp +++ b/engines/lure/menu.cpp @@ -212,8 +212,8 @@ void Menu::toggleHighlight(MenuRecord *menuRec) { void Menu::toggleHighlightItem(uint8 index) { byte *p = _surfaceMenu->data().data() + (DIALOG_EDGE_SIZE + 3 + - ((index - 1) * 8)) * _surfaceMenu->width(); - uint32 numBytes = 8 * _surfaceMenu->width(); + ((index - 1) * (FONT_HEIGHT - 1))) * _surfaceMenu->width(); + uint32 numBytes = (FONT_HEIGHT - 1) * _surfaceMenu->width(); while (numBytes-- > 0) { if (*p == MENU_UNSELECTED_COLOUR) *p = MENU_SELECTED_COLOUR; diff --git a/engines/lure/res.cpp b/engines/lure/res.cpp index 821c4103ac..819a1eacea 100644 --- a/engines/lure/res.cpp +++ b/engines/lure/res.cpp @@ -28,6 +28,8 @@ namespace Lure { +using namespace Common; + static Resources *int_resources = NULL; Resources &Resources::getReference() { @@ -597,4 +599,21 @@ void Resources::setTalkData(uint16 offset) { error("Unknown talk entry offset %d requested", offset); } +void Resources::saveToStream(Common::WriteStream *stream) +{ + _hotspotData.saveToStream(stream); + _activeHotspots.saveToStream(stream); + _fieldList.saveToStream(stream); +} + +void Resources::loadFromStream(Common::ReadStream *stream) { + debugC(ERROR_DETAILED, kLureDebugScripts, "Loading hotspot data"); + _hotspotData.loadFromStream(stream); + debugC(ERROR_DETAILED, kLureDebugScripts, "Loading active hotspots"); + _activeHotspots.loadFromStream(stream); + debugC(ERROR_DETAILED, kLureDebugScripts, "Loading fields"); + _fieldList.loadFromStream(stream); + debugC(ERROR_DETAILED, kLureDebugScripts, "Finished loading"); +} + } // end of namespace Lure diff --git a/engines/lure/res.h b/engines/lure/res.h index c29fd80c30..abf3108b16 100644 --- a/engines/lure/res.h +++ b/engines/lure/res.h @@ -29,6 +29,7 @@ #include "lure/res_struct.h" #include "lure/hotspots.h" #include "lure/palette.h" +#include "common/file.h" namespace Lure { @@ -161,6 +162,8 @@ public: void addHotspot(Hotspot *hotspot); void deactivateHotspot(uint16 hotspotId, bool isDestId = false); void deactivateHotspot(Hotspot *hotspot); + void saveToStream(Common::WriteStream *stream); + void loadFromStream(Common::ReadStream *stream); }; } // End of namespace Lure diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp index e7ed3bc075..28cbabd0c9 100644 --- a/engines/lure/res_struct.cpp +++ b/engines/lure/res_struct.cpp @@ -313,6 +313,108 @@ HotspotData::HotspotData(HotspotResource *rec) { actionHotspotId = 0; } +void HotspotData::saveToStream(WriteStream *stream) { + // Write out the basic fields + stream->writeUint16LE(descId); + stream->writeUint16LE(descId2); + stream->writeUint32LE(actions); + stream->writeByte(flags); + stream->writeByte(flags2); + stream->writeByte(headerFlags); + stream->writeSint16LE(startX); + stream->writeSint16LE(startY); + stream->writeUint16LE(roomNumber); + + stream->writeUint16LE(width); + stream->writeUint16LE(height); + stream->writeUint16LE(widthCopy); + stream->writeUint16LE(heightCopy); + stream->writeUint16LE(yCorrection); + stream->writeUint16LE(sequenceOffset); + stream->writeUint16LE(tickProcOffset); + stream->writeUint16LE(tickTimeout); + stream->writeUint16LE(tickSequenceOffset); + stream->writeUint16LE(characterMode); + stream->writeUint16LE(delayCtr); + + // Write out the runtime fields + stream->writeUint16LE(actionCtr); + stream->writeUint16LE(blockedState); + stream->writeByte(coveredFlag); + stream->writeUint16LE(talkMessageId); + stream->writeUint16LE(talkDestCharacterId); + stream->writeUint16LE(talkCountdown); + stream->writeUint16LE(pauseCtr); + stream->writeUint16LE(useHotspotId); + stream->writeUint16LE(use2HotspotId); + stream->writeUint16LE(v2b); + stream->writeUint16LE(actionHotspotId); +} + +void HotspotData::loadFromStream(ReadStream *stream) { + // Read in the basic fields + descId = stream->readUint16LE(); + descId2 = stream->readUint16LE(); + actions = stream->readUint32LE(); + flags = stream->readByte(); + flags2 = stream->readByte(); + headerFlags = stream->readByte(); + startX = stream->readSint16LE(); + startY = stream->readSint16LE(); + roomNumber = stream->readUint16LE(); + + width = stream->readUint16LE(); + height = stream->readUint16LE(); + widthCopy = stream->readUint16LE(); + heightCopy = stream->readUint16LE(); + yCorrection = stream->readUint16LE(); + sequenceOffset = stream->readUint16LE(); + tickProcOffset = stream->readUint16LE(); + tickTimeout = stream->readUint16LE(); + tickSequenceOffset = stream->readUint16LE(); + characterMode = (CharacterMode) stream->readUint16LE(); + delayCtr = stream->readUint16LE(); + + // Read in the runtime fields + actionCtr = stream->readUint16LE(); + blockedState = (BlockedState)stream->readUint16LE(); + coveredFlag = stream->readByte() != 0; + talkMessageId = stream->readUint16LE(); + talkDestCharacterId = stream->readUint16LE(); + talkCountdown = stream->readUint16LE(); + pauseCtr = stream->readUint16LE(); + useHotspotId = stream->readUint16LE(); + use2HotspotId = stream->readUint16LE(); + v2b = stream->readUint16LE(); + actionHotspotId = stream->readUint16LE(); +} + +// Hotspot data list + +void HotspotDataList::saveToStream(WriteStream *stream) { + iterator i; + for (i = begin(); i != end(); ++i) + { + HotspotData *hotspot = *i; + stream->writeUint16LE(hotspot->hotspotId); + hotspot->saveToStream(stream); + } + stream->writeUint16LE(0); +} + +void HotspotDataList::loadFromStream(ReadStream *stream) { + Resources &res = Resources::getReference(); + iterator i; + uint16 hotspotId = stream->readUint16LE(); + while (hotspotId != 0) + { + HotspotData *hotspot = res.getHotspot(hotspotId); + assert(hotspot); + hotspot->loadFromStream(stream); + hotspotId = stream->readUint16LE(); + } +} + // Hotspot override data HotspotOverrideData::HotspotOverrideData(HotspotOverrideResource *rec) { @@ -876,4 +978,40 @@ void ValueTableData::setField(FieldName fieldName, uint16 value) { setField((uint16) fieldName, value); } +void ValueTableData::saveToStream(Common::WriteStream *stream) +{ + // Write out the special fields + stream->writeUint16LE(_numGroats); + stream->writeSint16LE(_playerNewPos.position.x); + stream->writeSint16LE(_playerNewPos.position.y); + stream->writeUint16LE(_playerNewPos.roomNumber); + stream->writeByte(_playerPendingPos.isSet); + stream->writeSint16LE(_playerPendingPos.pos.x); + stream->writeSint16LE(_playerPendingPos.pos.y); + stream->writeByte(_flags); + stream->writeByte(_hdrFlagMask); + + // Write out the special fields + for (int index = 0; index < NUM_VALUE_FIELDS; ++index) + stream->writeUint16LE(_fieldList[index]); +} + +void ValueTableData::loadFromStream(Common::ReadStream *stream) +{ + // Load special fields + _numGroats = stream->readUint16LE(); + _playerNewPos.position.x = stream->readSint16LE(); + _playerNewPos.position.y = stream->readSint16LE(); + _playerNewPos.roomNumber = stream->readUint16LE(); + _playerPendingPos.isSet = stream->readByte() != 0; + _playerPendingPos.pos.x = stream->readSint16LE(); + _playerPendingPos.pos.y = stream->readSint16LE(); + _flags = stream->readByte(); + _hdrFlagMask = stream->readByte(); + + // Read in the field list + for (int index = 0; index < NUM_VALUE_FIELDS; ++index) + _fieldList[index] = stream->readUint16LE(); +} + } // end of namespace Lure diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h index b6e4f56502..e2b41bbe86 100644 --- a/engines/lure/res_struct.h +++ b/engines/lure/res_struct.h @@ -25,6 +25,7 @@ #include "lure/luredefs.h" #include "common/list.h" +#include "common/file.h" namespace Lure { @@ -438,9 +439,15 @@ public: void enable() { flags |= 0x80; } void disable() { flags &= 0x7F; } Direction nonVisualDirection() { return (Direction) scriptLoadFlag; } + void saveToStream(WriteStream *stream); + void loadFromStream(ReadStream *stream); }; -typedef ManagedList<HotspotData *> HotspotDataList; +class HotspotDataList: public ManagedList<HotspotData *> { +public: + void saveToStream(WriteStream *stream); + void loadFromStream(ReadStream *stream); +}; class HotspotOverrideData { public: @@ -736,6 +743,9 @@ public: uint8 &hdrFlagMask() { return _hdrFlagMask; } PlayerNewPosition &playerNewPos() { return _playerNewPos; } PlayerPendingPosition &playerPendingPos() { return _playerPendingPos; } + + void saveToStream(Common::WriteStream *stream); + void loadFromStream(Common::ReadStream *stream); }; } // End of namespace Lure diff --git a/engines/lure/room.cpp b/engines/lure/room.cpp index d47fa2e372..a97ef174dc 100644 --- a/engines/lure/room.cpp +++ b/engines/lure/room.cpp @@ -311,7 +311,8 @@ void Room::addLayers(Hotspot &h) { int16 yStart = hsY / RECT_SIZE; int16 yEnd = (hsY + h.heightCopy() - 1) / RECT_SIZE; int16 numY = yEnd - yStart + 1; - +debugC(ERROR_BASIC, kLureDebugAnimations, "p=(%d,%d) rp=(%d,%d) size=(%d,%d)", + hsX, hsY, xStart, yStart, numX, numY); for (int16 xCtr = 0; xCtr < numX; ++xCtr, ++xStart) { int16 xs = xStart - 4; if (xs < 0) continue; @@ -397,7 +398,6 @@ void Room::update() { } for (iTemp = tempList.begin(); iTemp != tempList.end(); ++iTemp) { Hotspot &h = *iTemp.operator*(); - flagCoveredCells(h); addAnimation(h); addLayers(h); @@ -615,4 +615,20 @@ bool Room::checkInTalkDialog() { (mouse.y() < _talkDialogY + _talkDialog->surface().height())); } +void Room::saveToStream(Common::WriteStream *stream) { + stream->writeUint16LE(_roomNumber); + stream->writeUint16LE(_destRoomNumber); + stream->writeByte(_showInfo); + stream->writeUint16LE(_cursorState); +} + +void Room::loadFromStream(Common::ReadStream *stream) { + int roomNum = stream->readUint16LE(); + setRoomNumber(roomNum, false); + + _destRoomNumber = stream->readUint16LE(); + _showInfo = stream->readByte() != 0; + _cursorState = (CursorState) stream->readUint16LE(); +} + } // end of namespace Lure diff --git a/engines/lure/room.h b/engines/lure/room.h index ba32496997..1a9b664a53 100644 --- a/engines/lure/room.h +++ b/engines/lure/room.h @@ -108,6 +108,8 @@ public: void setCursorState(CursorState state) { _cursorState = state; } bool checkInTalkDialog(); char *statusLine() { return _statusLine; } + void saveToStream(Common::WriteStream *stream); + void loadFromStream(Common::ReadStream *stream); }; } // end of namespace Lure |