diff options
| -rw-r--r-- | queen/defs.h | 2 | ||||
| -rw-r--r-- | queen/input.cpp | 9 | ||||
| -rw-r--r-- | queen/input.h | 15 | ||||
| -rw-r--r-- | queen/logic.cpp | 171 | ||||
| -rw-r--r-- | queen/logic.h | 2 | ||||
| -rw-r--r-- | queen/queen.cpp | 2 | ||||
| -rw-r--r-- | queen/resource.cpp | 38 | ||||
| -rw-r--r-- | queen/resource.h | 9 | ||||
| -rw-r--r-- | queen/structs.h | 54 | 
9 files changed, 297 insertions, 5 deletions
| diff --git a/queen/defs.h b/queen/defs.h index 8be1467825..112e54cfd0 100644 --- a/queen/defs.h +++ b/queen/defs.h @@ -27,6 +27,8 @@ namespace Queen {  // Maybe should be an inlined function somwhere else, feel free to change  #define InRange(x,l,h)     ((x)<=(h) && (x)>=(l)) /* X in [l..h] */ +#define SAVEGAME_SIZE	24622 +  enum {  	COMPRESSION_NONE  = 0,  	COMPRESSION_MP3   = 1,	 diff --git a/queen/input.cpp b/queen/input.cpp index 558702dc80..f0ecf3ae30 100644 --- a/queen/input.cpp +++ b/queen/input.cpp @@ -38,6 +38,7 @@ const char* Input::_commandKeys[LANGUAGE_COUNT] = {  Input::Input(Language language, OSystem *system) :   	_system(system), _fastMode(false), _keyVerb(VERB_NONE),   	_cutawayRunning(false), _cutawayQuit(false), _talkQuit(false), +	_quickSave(false), _quickLoad(false),  	_inKey(0), _mouse_x(0), _mouse_y(0), _mouseButton(0) {  	switch (language) { @@ -186,6 +187,14 @@ int Input::checkKeys() {  			}  			break; +		case KEY_F11:	// Quicksave +			_quickSave = true; +			break; +			 +		case KEY_F12:	// Quickload +			_quickLoad = true; +			break; +  		default:  			if(_inKey == _currentCommandKeys[0])  				_keyVerb = Verb(VERB_OPEN); diff --git a/queen/input.h b/queen/input.h index d9a047a84f..ff93b94a50 100644 --- a/queen/input.h +++ b/queen/input.h @@ -72,6 +72,11 @@ class Input {  		bool talkQuit() const { return _talkQuit; }  		void talkQuitReset()  { _talkQuit = false; } +		bool quickSave() const { return _quickSave; } +		void quickSaveReset()  { _quickSave = false; } +		bool quickLoad() const { return _quickLoad; } +		void quickLoadReset()  { _quickLoad = false; } +  		bool fastMode() const { return _fastMode; }  		void fastMode(bool fm)	{ _fastMode = fm; } @@ -102,7 +107,9 @@ class Input {  			KEY_RETURN    = 13,  			KEY_BACKSPACE = 8, -			KEY_F1 = 282 +			KEY_F1 = 282, +			KEY_F11 = KEY_F1 + 10, +			KEY_F12  		};  		enum  @@ -131,6 +138,12 @@ class Input {  		//! moved Talk::_quit here   		bool _talkQuit;         // TALKQUIT +		//! Set if quicksave requested +		bool _quickSave; + +		//! Set if quickload requested +		bool _quickLoad; +  		//! Set by delay();  		int _inKey; diff --git a/queen/logic.cpp b/queen/logic.cpp index 56387977a6..fd21ee9024 100644 --- a/queen/logic.cpp +++ b/queen/logic.cpp @@ -2321,6 +2321,177 @@ void Logic::update() {  	BobSlot *joe = _graphics->bob(0);  	_display->update(joe->active, joe->x, joe->y);  	_dbg->update(_input->checkKeys()); + +	if (_input->quickSave()) +		if (!_input->cutawayRunning()) { +			_input->quickSaveReset(); +			gameSave(0, "Quicksave"); +		} +	if (_input->quickLoad()) +		if (!_input->cutawayRunning()) { +			_input->quickLoadReset(); +			gameLoad(0); +		} +} + +bool Logic::gameSave(uint16 slot, const char *desc) { +	if (!desc)	//no description entered +		return false; + +	debug(3, "Saving game to slot %d", slot); +	 +	int i, j; +	char *buf = new char[32]; +	memcpy(buf, desc, strlen(desc) < 32 ? strlen(desc) : 32); +	for (i = strlen(desc); i < 32; i++) +		buf[i] = '\0'; +	byte *saveData = new byte[SAVEGAME_SIZE]; +	byte *ptr = saveData; +	memcpy(ptr, buf, 32); ptr += 32; +	 +	WRITE_BE_UINT16(ptr, _settings.talkSpeed); ptr += 2; +	WRITE_BE_UINT16(ptr, _settings.musicVolume); ptr += 2; +	WRITE_BE_UINT16(ptr, _settings.sfxToggle ? 1 : 0); ptr += 2; +	WRITE_BE_UINT16(ptr, _settings.speechToggle ? 1 : 0); ptr += 2; +	WRITE_BE_UINT16(ptr, _settings.musicToggle ? 1 : 0); ptr += 2; +	WRITE_BE_UINT16(ptr, _settings.textToggle ? 1 : 0); ptr += 2; +	 +	for (i = 0; i < 4; i++) { +		WRITE_BE_UINT16(ptr, _inventoryItem[i]); ptr += 2; +	} +	 +	WRITE_BE_UINT16(ptr, _graphics->bob(0)->x); ptr += 2; +	WRITE_BE_UINT16(ptr, _graphics->bob(0)->y); ptr += 2; +	WRITE_BE_UINT16(ptr, _currentRoom); ptr += 2; + +	for (i = 1; i <= _numObjects; i++) +		_objectData[i].writeTo(ptr); +		 +	for (i = 1; i <= _numItems; i++) +		_itemData[i].writeTo(ptr); +		 +	for (i = 0; i < GAME_STATE_COUNT; i++) { +		WRITE_BE_UINT16(ptr, gameState(i)); ptr += 2; +	} +	 +	for (i = 1; i <= _numRooms; i++) +		for (j = 1; j <= _areaMax[i]; j++) +			_area[i][j].writeTo(ptr); +			 +	for (i = 0; i <= 85; i++) +			_talkSelected[i].writeTo(ptr); +	 +	for (i = 1; i <= _numWalkOffs; i++) +		_walkOffData[i].writeTo(ptr); + +	WRITE_BE_UINT16(ptr, _joe.facing); ptr += 2; +	WRITE_BE_UINT16(ptr, 0); ptr += 2; //TODO: tmpbamflag +	WRITE_BE_UINT16(ptr, 0); ptr += 2; //TODO: lastoverride +	 +	//TODO: lastmerge, lastalter, altmrgpri +	for (i = 0; i < 3; i++) { +		WRITE_BE_UINT16(ptr, 0); ptr += 2; +	} +	 +	if ((ptr - saveData) != SAVEGAME_SIZE) { +		delete[] saveData; +		return false; +	} +	 +	bool result = _resource->writeSave(slot, saveData, SAVEGAME_SIZE); +	delete[] saveData; +	 +	return result;	 +} + +bool Logic::gameLoad(uint16 slot) { +	int i, j; +	byte *saveData = new byte[SAVEGAME_SIZE]; +	byte *ptr = saveData; +	if (!_resource->readSave(slot, saveData)) { +		warning("Couldn't load savegame from slot %d", slot); +		delete[] saveData; +		return false; +	} +	 +	debug(3, "Loading game from slot %d", slot); +	ptr += 32;	//skip description +	_settings.talkSpeed = (int16)READ_BE_UINT16(ptr); ptr += 2; +	_settings.musicVolume = (int16)READ_BE_UINT16(ptr); ptr += 2; +	_settings.sfxToggle = READ_BE_UINT16(ptr) != 0; ptr += 2; +	_settings.speechToggle = READ_BE_UINT16(ptr) != 0; ptr += 2; +	_settings.musicToggle = READ_BE_UINT16(ptr) != 0; ptr += 2; +	_settings.textToggle = READ_BE_UINT16(ptr) != 0; ptr += 2; + +	for (i = 0; i < 4; i++) { +		_inventoryItem[i] = (int16)READ_BE_UINT16(ptr); ptr += 2; +	} + +	_joe.x = (int16)READ_BE_UINT16(ptr); ptr += 2; +	_joe.y = (int16)READ_BE_UINT16(ptr); ptr += 2; + +	currentRoom(READ_BE_UINT16(ptr)); ptr += 2; +	 +	for (i = 1; i <= _numObjects; i++) +		_objectData[i].readFrom(ptr); + +	for (i = 1; i <= _numItems; i++) +		_itemData[i].readFrom(ptr); + +	for (i = 0; i < GAME_STATE_COUNT; i++) { +		gameState(i, (int16)READ_BE_UINT16(ptr)); ptr += 2; +	} + +	for (i = 1; i <= _numRooms; i++) +		for (j = 1; j <= _areaMax[i]; j++) +			_area[i][j].readFrom(ptr); +	 +	for (i = 0; i <= 85; i++) +		_talkSelected[i].readFrom(ptr); +		 +	for (i = 1; i <= _numWalkOffs; i++) +		_walkOffData[i].readFrom(ptr); + +	joeFacing(READ_BE_UINT16(ptr));  ptr += 2; +	READ_BE_UINT16(ptr); ptr += 2;	//TODO: tmpbamflag +	READ_BE_UINT16(ptr); ptr += 2; //TODO: lastoverride +	//_sound->playSound(_sound->lastOverride()) +	 +	//TODO: lastmerge, lastalter, altmrgpri +	for (i = 0; i < 3; i++) { +		READ_BE_UINT16(ptr); ptr += 2; +	} + +	if ((ptr - saveData) != SAVEGAME_SIZE) { +		delete[] saveData; +		return false; +	} +	 +	//CUTJOEF = _joe.facing; +	joeFace(); +	 +	//OLDX = _joe.x; +	//OLDY = _joe.y; +	_oldRoom = 0; +	newRoom(_currentRoom); +	_entryObj = 0; + +	switch (gameState(VAR_DRESSING_MODE)) { +		case  0:  +			joeUseClothes(false); +			break; +		case  1: +			joeUseUnderwear(); +			break; +		case  2: +			joeUseDress(false); +			break; +	} +	inventoryRefresh(); +	//bamflag = .. +	 +	delete[] saveData; +	return true;  }  void Logic::sceneStart(bool showMouseCursor) { diff --git a/queen/logic.h b/queen/logic.h index 6aefbfdcfa..eb9b5c1a06 100644 --- a/queen/logic.h +++ b/queen/logic.h @@ -298,6 +298,8 @@ public:  	void update(); +	bool gameSave(uint16 slot, const char *desc); +	bool gameLoad(uint16 slot);  	enum {  		MAX_ZONES_NUMBER   = 32, diff --git a/queen/queen.cpp b/queen/queen.cpp index 8b5f56dd3c..3b9939c34f 100644 --- a/queen/queen.cpp +++ b/queen/queen.cpp @@ -220,7 +220,7 @@ void QueenEngine::go() {  }  void QueenEngine::initialise(void) { -	_resource = new Resource(_gameDataPath, _detector->_game.detectname); +	_resource = new Resource(_gameDataPath, _detector->_game.detectname,  _system->get_savefile_manager(), getSavePath());  	_input = new Input(_resource->getLanguage(), _system);  	_display = new Display(_system, _input);  	_graphics = new Graphics(_display, _input, _resource); diff --git a/queen/resource.cpp b/queen/resource.cpp index 5c2a5f7781..439a73b9c6 100644 --- a/queen/resource.cpp +++ b/queen/resource.cpp @@ -46,8 +46,8 @@ const GameVersion Resource::_gameVersions[] = {  }; -Resource::Resource(const Common::String &datafilePath, const char *datafileName) -	: _JAS2Pos(0), _datafilePath(datafilePath), _resourceEntries(0), _resourceTable(NULL) { +Resource::Resource(const Common::String &datafilePath, const char *datafileName, SaveFileManager *mgr, const char *savePath) +	: _JAS2Pos(0), _datafilePath(datafilePath), _resourceEntries(0), _resourceTable(NULL), _saveFileManager(mgr), _savePath(savePath) {  	_resourceFile = new File();  	_resourceFile->open(datafileName, _datafilePath); @@ -261,5 +261,39 @@ File *Resource::giveCompressedSound(const char *filename) {  	return _resourceFile;  } +bool Resource::writeSave(uint16 slot, const byte *saveData, uint32 size) { +	char name[20]; +	sprintf(name, "queensav.%03d", slot); +	SaveFile *file = _saveFileManager->open_savefile(name, _savePath, true); +	if (!file) { +		warning("Can't create file '%s', game not saved", name); +		return false; +	} + +	if (file->write(saveData, size) != size) { +		warning("Can't write file '%s'. (Disk full?)", name); +		return false; +	} + +	delete file; +	return true; +} + +bool Resource::readSave(uint16 slot, byte *&ptr) { +	char name[20]; +	sprintf(name, "queensav.%03d", slot); +	SaveFile *file = _saveFileManager->open_savefile(name, _savePath, false); +	if (!file) +		return false; + +	if (file->read(ptr, SAVEGAME_SIZE) != SAVEGAME_SIZE) { +		warning("Can't read from file '%s'", name); +		delete file; +		return false; +	} + +	return true; +} +  } // End of namespace Queen diff --git a/queen/resource.h b/queen/resource.h index 611c7c63f4..d3e4e20c33 100644 --- a/queen/resource.h +++ b/queen/resource.h @@ -23,6 +23,7 @@  #define QUEEN_RESOURCE_H  #include "common/file.h" +#include "common/savefile.h"  #include "defs.h"  namespace Queen { @@ -62,7 +63,7 @@ struct GameVersion {  class Resource {  public: -	Resource(const Common::String &datafilePath, const char *datafileName); +	Resource(const Common::String &datafilePath, const char *datafileName, SaveFileManager *mgr, const char *savePath);  	~Resource(void);  	uint8 *loadFile(const char *filename, uint32 skipBytes = 0, byte *dstBuf = NULL);  	uint8 *loadFileMalloc(const char *filename, uint32 skipBytes = 0, byte *dstBuf = NULL); @@ -76,6 +77,9 @@ public:  	File *giveCompressedSound(const char *filename);  	Language getLanguage();  	const char *JASVersion(); +	bool writeSave(uint16 slot, const byte *saveData, uint32 size); +	bool readSave(uint16 slot, byte *&ptr); +  protected:  	File *_resourceFile; @@ -84,6 +88,7 @@ protected:  	uint8 _compression;  	const Common::String _datafilePath;  	const GameVersion *_gameVersion; +	const char *_savePath;  	uint32 _resourceEntries;  	ResourceEntry *_resourceTable;  	static const GameVersion _gameVersions[]; @@ -93,6 +98,8 @@ protected:  	bool readTableFile();  	void readTableCompResource();  	static const GameVersion *detectGameVersion(uint32 dataFilesize); + +	SaveFileManager *_saveFileManager;  };  } // End of namespace Queen diff --git a/queen/structs.h b/queen/structs.h index 289ad7874e..10377e53cb 100644 --- a/queen/structs.h +++ b/queen/structs.h @@ -36,6 +36,13 @@ struct Box {  		y2 = (int16)READ_BE_UINT16(ptr); ptr += 2;  	} +	void writeTo(byte *&ptr) { +		WRITE_BE_UINT16(ptr, x1); ptr += 2; +		WRITE_BE_UINT16(ptr, y1); ptr += 2; +		WRITE_BE_UINT16(ptr, x2); ptr += 2; +		WRITE_BE_UINT16(ptr, y2); ptr += 2; +	} +  	int16 xDiff() const {  		return x2 - x1;  	} @@ -72,6 +79,14 @@ struct Area {  		object = READ_BE_UINT16(ptr); ptr += 2;  	} +	void writeTo(byte *&ptr) { +		WRITE_BE_UINT16(ptr, mapNeighbours); ptr += 2; +		box.writeTo(ptr); +		WRITE_BE_UINT16(ptr, bottomScaleFactor); ptr += 2; +		WRITE_BE_UINT16(ptr, topScaleFactor); ptr += 2; +		WRITE_BE_UINT16(ptr, object); ptr += 2; +	} +  	uint16 calcScale(int16 y) const {  		uint16 dy = box.y2 - box.y1;  		int16 ds = (int16)(topScaleFactor - bottomScaleFactor); @@ -103,6 +118,12 @@ struct WalkOffData {  		x = READ_BE_UINT16(ptr); ptr += 2;  		y = READ_BE_UINT16(ptr); ptr += 2;  	} + +	void writeTo(byte *&ptr) { +		WRITE_BE_UINT16(ptr, entryObj); ptr += 2; +		WRITE_BE_UINT16(ptr, x); ptr += 2; +		WRITE_BE_UINT16(ptr, y); ptr += 2; +	}  }; @@ -210,6 +231,17 @@ struct ObjectData {  		state = READ_BE_UINT16(ptr); ptr += 2;  		image = (int16)READ_BE_UINT16(ptr); ptr += 2;  	} + +	void writeTo(byte *&ptr) { +		WRITE_BE_UINT16(ptr, name); ptr += 2; +		WRITE_BE_UINT16(ptr, x); ptr += 2; +		WRITE_BE_UINT16(ptr, y); ptr += 2; +		WRITE_BE_UINT16(ptr, description); ptr += 2; +		WRITE_BE_UINT16(ptr, entryObj); ptr += 2; +		WRITE_BE_UINT16(ptr, room); ptr += 2; +		WRITE_BE_UINT16(ptr, state); ptr += 2; +		WRITE_BE_UINT16(ptr, image); ptr += 2; +	}  }; @@ -275,6 +307,14 @@ struct ItemData {  		frame = READ_BE_UINT16(ptr); ptr += 2;  		sfxDescription = (int16)READ_BE_UINT16(ptr); ptr += 2;  	} + +	void writeTo(byte *&ptr) { +		WRITE_BE_UINT16(ptr, name); ptr += 2; +		WRITE_BE_UINT16(ptr, description); ptr += 2; +		WRITE_BE_UINT16(ptr, state); ptr += 2; +		WRITE_BE_UINT16(ptr, frame); ptr += 2; +		WRITE_BE_UINT16(ptr, sfxDescription); ptr += 2; +	}  }; @@ -512,6 +552,20 @@ struct Person {  struct TalkSelected {  	int16 hasTalkedTo;  	int16 values[4]; + +	void readFrom(byte *&ptr) { +		hasTalkedTo = (int16)READ_BE_UINT16(ptr); ptr += 2; +		for (int i = 0; i < 4; i++) { +			values[i] = (int16)READ_BE_UINT16(ptr); ptr += 2; +		}	 +	} + +	void writeTo(byte *&ptr) { +		WRITE_BE_UINT16(ptr, hasTalkedTo); ptr += 2; +		for (int i = 0; i < 4; i++) { +			WRITE_BE_UINT16(ptr, values[i]); ptr += 2; +		} +	}  }; | 
