diff options
| -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 | 
