aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoost Peters2003-11-09 21:31:18 +0000
committerJoost Peters2003-11-09 21:31:18 +0000
commitb64c6fcbfc0898f8eb881f551e55d6695cc5dfd7 (patch)
tree5a536742f1b3ba1dd539e4a34f059b7f76d53eee
parent1b6e9a9b0099774efb1a80baf29275cca1075ebe (diff)
downloadscummvm-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.h2
-rw-r--r--queen/input.cpp9
-rw-r--r--queen/input.h15
-rw-r--r--queen/logic.cpp171
-rw-r--r--queen/logic.h2
-rw-r--r--queen/queen.cpp2
-rw-r--r--queen/resource.cpp38
-rw-r--r--queen/resource.h9
-rw-r--r--queen/structs.h54
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;
+ }
+ }
};