diff options
author | Joost Peters | 2003-11-09 21:31:18 +0000 |
---|---|---|
committer | Joost Peters | 2003-11-09 21:31:18 +0000 |
commit | b64c6fcbfc0898f8eb881f551e55d6695cc5dfd7 (patch) | |
tree | 5a536742f1b3ba1dd539e4a34f059b7f76d53eee | |
parent | 1b6e9a9b0099774efb1a80baf29275cca1075ebe (diff) | |
download | scummvm-rg350-b64c6fcbfc0898f8eb881f551e55d6695cc5dfd7.tar.gz scummvm-rg350-b64c6fcbfc0898f8eb881f551e55d6695cc5dfd7.tar.bz2 scummvm-rg350-b64c6fcbfc0898f8eb881f551e55d6695cc5dfd7.zip |
Added (quick-)Saving/Loading
svn-id: r11230
-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; + } + } }; |