aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2006-10-02 12:48:56 +0000
committerPaul Gilbert2006-10-02 12:48:56 +0000
commit1a96e26bf6bd9593da746e1cf3da98448df3a92d (patch)
treeb93ffac36b281447d64e08ce3d34a4511f4b6a89
parente8623fa477119e4b418200826e1bac372b9f8df4 (diff)
downloadscummvm-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.cpp10
-rw-r--r--engines/lure/hotspots.cpp250
-rw-r--r--engines/lure/hotspots.h21
-rw-r--r--engines/lure/lure.cpp107
-rw-r--r--engines/lure/lure.h7
-rw-r--r--engines/lure/luredefs.h1
-rw-r--r--engines/lure/menu.cpp4
-rw-r--r--engines/lure/res.cpp19
-rw-r--r--engines/lure/res.h3
-rw-r--r--engines/lure/res_struct.cpp138
-rw-r--r--engines/lure/res_struct.h12
-rw-r--r--engines/lure/room.cpp20
-rw-r--r--engines/lure/room.h2
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