aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2016-06-25 23:07:44 -0400
committerPaul Gilbert2016-07-15 19:25:03 -0400
commit04afc633794035cfcc0cb7030113d7750a7dbae3 (patch)
tree13eb89371f23cd0f28a7745a08c64b84b842dbb9
parent507924b39d0beb50bacb05f3ad15f66fc113f3a9 (diff)
downloadscummvm-rg350-04afc633794035cfcc0cb7030113d7750a7dbae3.tar.gz
scummvm-rg350-04afc633794035cfcc0cb7030113d7750a7dbae3.tar.bz2
scummvm-rg350-04afc633794035cfcc0cb7030113d7750a7dbae3.zip
TITANIC: Adding savegame header load/save methods
-rw-r--r--engines/titanic/core/project_item.cpp128
-rw-r--r--engines/titanic/core/project_item.h35
-rw-r--r--engines/titanic/support/simple_file.cpp31
-rw-r--r--engines/titanic/support/simple_file.h33
-rw-r--r--engines/titanic/titanic.cpp23
-rw-r--r--engines/titanic/titanic.h36
6 files changed, 275 insertions, 11 deletions
diff --git a/engines/titanic/core/project_item.cpp b/engines/titanic/core/project_item.cpp
index 7546f20936..c6a5c2eb61 100644
--- a/engines/titanic/core/project_item.cpp
+++ b/engines/titanic/core/project_item.cpp
@@ -22,6 +22,8 @@
#include "common/file.h"
#include "common/savefile.h"
+#include "graphics/scaler.h"
+#include "graphics/thumbnail.h"
#include "titanic/game_manager.h"
#include "titanic/titanic.h"
#include "titanic/core/dont_save_file_item.h"
@@ -32,6 +34,13 @@
namespace Titanic {
+#define CURRENT_SAVEGAME_VERSION 1
+#define MAX_SAVEGAME_SLOTS 99
+#define MINIMUM_SAVEGAME_VERSION 1
+
+static const char *const SAVEGAME_STR = "TNIC";
+#define SAVEGAME_STR_SIZE 4
+
void CFileListItem::save(SimpleFile *file, int indent) const {
file->writeNumberLine(0, indent);
file->writeQuotedLine(_name, indent);
@@ -158,6 +167,11 @@ void CProjectItem::loadGame(int slotId) {
file.open(newFile);
}
+ // Load the savegame header in
+ TitanicSavegameHeader header;
+ readSavegameHeader(&file, header);
+ delete header._thumbnail;
+
// Load the contents in
CProjectItem *newProject = loadData(&file);
file.IsClassStart();
@@ -183,7 +197,7 @@ void CProjectItem::loadGame(int slotId) {
postLoad();
}
-void CProjectItem::saveGame(int slotId) {
+void CProjectItem::saveGame(int slotId, const CString &desc) {
CompressedFile file;
Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(
Common::String::format("slot%d.gam", slotId));
@@ -192,6 +206,11 @@ void CProjectItem::saveGame(int slotId) {
// Signal the game is being saved
preSave();
+ // Write out the savegame header
+ TitanicSavegameHeader header;
+ header._saveName = desc;
+ writeSavegameHeader(&file, header);
+
// Save the contents out
saveData(&file, this);
@@ -411,4 +430,111 @@ CViewItem *CProjectItem::findView(int roomNumber, int nodeNumber, int viewNumber
return nullptr;
}
+SaveStateList CProjectItem::getSavegameList(const Common::String &target) {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray filenames;
+ Common::String saveDesc;
+ Common::String pattern = Common::String::format("%s.0??", target.c_str());
+ TitanicSavegameHeader header;
+
+ filenames = saveFileMan->listSavefiles(pattern);
+ sort(filenames.begin(), filenames.end()); // Sort to get the files in numerical order
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ const char *ext = strrchr(file->c_str(), '.');
+ int slot = ext ? atoi(ext + 1) : -1;
+
+ if (slot >= 0 && slot < MAX_SAVEGAME_SLOTS) {
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
+
+ if (in) {
+ SimpleFile f;
+ f.open(in);
+ if (!readSavegameHeader(&f, header))
+ continue;
+
+ saveList.push_back(SaveStateDescriptor(slot, header._saveName));
+
+ header._thumbnail->free();
+ delete header._thumbnail;
+ delete in;
+ }
+ }
+ }
+
+ return saveList;
+}
+
+bool CProjectItem::readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header) {
+ char saveIdentBuffer[SAVEGAME_STR_SIZE + 1];
+ header._thumbnail = nullptr;
+
+ // Validate the header Id
+ file->unsafeRead(saveIdentBuffer, SAVEGAME_STR_SIZE + 1);
+ if (strncmp(saveIdentBuffer, SAVEGAME_STR, SAVEGAME_STR_SIZE)) {
+ file->seek(-SAVEGAME_STR_SIZE, SEEK_CUR);
+ header._saveName = "Unnamed";
+ return true;
+ }
+
+ header._version = file->readByte();
+ if (header._version < MINIMUM_SAVEGAME_VERSION || header._version > CURRENT_SAVEGAME_VERSION)
+ return false;
+
+ // Read in the string
+ header._saveName.clear();
+ char ch;
+ while ((ch = (char)file->readByte()) != '\0') header._saveName += ch;
+
+ // Get the thumbnail
+ header._thumbnail = Graphics::loadThumbnail(*file);
+ if (!header._thumbnail)
+ return false;
+
+ // Read in save date/time
+ header._year = file->readUint16LE();
+ header._month = file->readUint16LE();
+ header._day = file->readUint16LE();
+ header._hour = file->readUint16LE();
+ header._minute = file->readUint16LE();
+ header._totalFrames = file->readUint32LE();
+
+ return true;
+}
+
+void CProjectItem::writeSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header) {
+ // Write out a savegame header
+ file->write(SAVEGAME_STR, SAVEGAME_STR_SIZE + 1);
+
+ file->writeByte(CURRENT_SAVEGAME_VERSION);
+
+ // Write savegame name
+ file->write(header._saveName.c_str(), header._saveName.size());
+ file->writeByte('\0');
+
+ // Create a thumbnail of the screen and save it out
+ Graphics::Surface *thumb = createThumbnail();
+ Graphics::saveThumbnail(*file, *thumb);
+ thumb->free();
+ delete thumb;
+
+ // Write out the save date/time
+ TimeDate td;
+ g_system->getTimeAndDate(td);
+ file->writeUint16LE(td.tm_year + 1900);
+ file->writeUint16LE(td.tm_mon + 1);
+ file->writeUint16LE(td.tm_mday);
+ file->writeUint16LE(td.tm_hour);
+ file->writeUint16LE(td.tm_min);
+ file->writeUint16LE(g_vm->_events->getFrameCounter());
+}
+
+Graphics::Surface *CProjectItem::createThumbnail() {
+ Graphics::Surface *thumb = new Graphics::Surface();
+
+ ::createThumbnailFromScreen(thumb);
+ return thumb;
+}
+
} // End of namespace Titanic
diff --git a/engines/titanic/core/project_item.h b/engines/titanic/core/project_item.h
index 0807460852..213fa9d638 100644
--- a/engines/titanic/core/project_item.h
+++ b/engines/titanic/core/project_item.h
@@ -24,6 +24,9 @@
#define TITANIC_PROJECT_ITEM_H
#include "common/scummsys.h"
+#include "common/str.h"
+#include "engines/savestate.h"
+#include "graphics/surface.h"
#include "titanic/support/simple_file.h"
#include "titanic/core/dont_save_file_item.h"
#include "titanic/core/file_item.h"
@@ -32,6 +35,16 @@
namespace Titanic {
+struct TitanicSavegameHeader {
+ uint8 _version;
+ CString _saveName;
+ Graphics::Surface *_thumbnail;
+ int _year, _month, _day;
+ int _hour, _minute;
+ int _totalFrames;
+};
+
+
class CGameManager;
class CPetControl;
class CViewItem;
@@ -117,6 +130,26 @@ private:
* Save project data to the passed file
*/
void saveData(SimpleFile *file, CTreeItem *item) const;
+
+ /**
+ * Creates a thumbnail for the current on-screen contents
+ */
+ static Graphics::Surface *createThumbnail();
+public:
+ /**
+ * Load a list of savegames
+ */
+ static SaveStateList getSavegameList(const Common::String &target);
+
+ /**
+ * Write out the header information for a savegame
+ */
+ static void writeSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header);
+
+ /**
+ * Read in the header information for a savegame
+ */
+ static bool readSavegameHeader(SimpleFile *file, TitanicSavegameHeader &header);
public:
CLASSDEF
CProjectItem();
@@ -159,7 +192,7 @@ public:
/**
* Save the entire project data to a given savegame slot
*/
- void saveGame(int slotId);
+ void saveGame(int slotId, const CString &desc);
/**
* Clear any currently loaded project
diff --git a/engines/titanic/support/simple_file.cpp b/engines/titanic/support/simple_file.cpp
index 45b5c8a7cb..e60b7c7485 100644
--- a/engines/titanic/support/simple_file.cpp
+++ b/engines/titanic/support/simple_file.cpp
@@ -89,12 +89,29 @@ size_t SimpleFile::write(const void *src, size_t count) const {
return _outStream->write(src, count);
}
+void SimpleFile::seek(int offset, int origin) {
+ assert(_inStream);
+ _inStream->seek(offset, origin);
+}
+
byte SimpleFile::readByte() {
byte b;
safeRead(&b, 1);
return b;
}
+uint SimpleFile::readUint16LE() {
+ uint val;
+ safeRead(&val, 2);
+ return READ_LE_UINT16(&val);
+}
+
+uint SimpleFile::readUint32LE() {
+ uint val;
+ safeRead(&val, 4);
+ return READ_LE_UINT32(&val);
+}
+
CString SimpleFile::readString() {
char c;
CString result;
@@ -248,6 +265,20 @@ void SimpleFile::readBuffer(char *buffer, size_t count) {
}
}
+void SimpleFile::writeUint16LE(uint val) {
+ byte lo = val & 0xff;
+ byte hi = (val >> 8) & 0xff;
+ write(&lo, 1);
+ write(&hi, 1);
+}
+
+void SimpleFile::writeUint32LE(uint val) {
+ uint16 lo = val & 0xffff;
+ uint16 hi = (val >> 16) & 0xff;
+ writeUint16LE(lo);
+ writeUint16LE(hi);
+}
+
void SimpleFile::writeLine(const CString &str) const {
write(str.c_str(), str.size());
write("\r\n", 2);
diff --git a/engines/titanic/support/simple_file.h b/engines/titanic/support/simple_file.h
index bca96a631a..a83e5922e2 100644
--- a/engines/titanic/support/simple_file.h
+++ b/engines/titanic/support/simple_file.h
@@ -61,6 +61,9 @@ public:
SimpleFile();
virtual ~SimpleFile();
+ operator Common::SeekableReadStream &() { return *_inStream; }
+ operator Common::WriteStream &() { return *_outStream; }
+
/**
* Set up a stream for read access
*/
@@ -92,11 +95,26 @@ public:
virtual size_t write(const void *src, size_t count) const;
/**
+ * Seek
+ */
+ virtual void seek(int offset, int origin);
+
+ /**
* Read a byte
*/
byte readByte();
/**
+ * Read a 16-bit LE number
+ */
+ uint readUint16LE();
+
+ /**
+ * Read a 32-bit LE number
+ */
+ uint readUint32LE();
+
+ /**
* Read a string from the file
*/
CString readString();
@@ -137,6 +155,21 @@ public:
bool scanf(const char *format, ...);
/**
+ * Write out a byte
+ */
+ void writeByte(byte b) { write(&b, 1); }
+
+ /**
+ * Write out a raw 16-bit LE number
+ */
+ void writeUint16LE(uint val);
+
+ /**
+ * Write out a raw 32-bit LE number
+ */
+ void writeUint32LE(uint val);
+
+ /**
* Write a string line
*/
void writeLine(const CString &str) const;
diff --git a/engines/titanic/titanic.cpp b/engines/titanic/titanic.cpp
index 9d44cd6141..ab734d9eeb 100644
--- a/engines/titanic/titanic.cpp
+++ b/engines/titanic/titanic.cpp
@@ -157,4 +157,27 @@ void TitanicEngine::setRoomNames() {
delete r;
}
+
+bool TitanicEngine::canLoadGameStateCurrently() {
+ return _window->_inputAllowed;
+}
+
+bool TitanicEngine::canSaveGameStateCurrently() {
+ return _window->_inputAllowed;
+}
+
+Common::Error TitanicEngine::loadGameState(int slot) {
+ _window->_project->loadGame(slot);
+ return Common::kNoError;
+}
+
+Common::Error TitanicEngine::saveGameState(int slot, const Common::String &desc) {
+ _window->_project->saveGame(slot, desc);
+ return Common::kNoError;
+}
+
+CString TitanicEngine::generateSaveName(int slot) {
+ return CString::format("%s.%03d", _targetName.c_str(), slot);
+}
+
} // End of namespace Titanic
diff --git a/engines/titanic/titanic.h b/engines/titanic/titanic.h
index 4391796e51..9acf78cbf2 100644
--- a/engines/titanic/titanic.h
+++ b/engines/titanic/titanic.h
@@ -73,15 +73,6 @@ enum TitanicDebugChannels {
struct TitanicGameDescription;
class TitanicEngine;
-struct TitanicSavegameHeader {
- uint8 _version;
- Common::String _saveName;
- Graphics::Surface *_thumbnail;
- int _year, _month, _day;
- int _hour, _minute;
- int _totalFrames;
-};
-
class TitanicEngine : public Engine {
private:
/**
@@ -133,6 +124,27 @@ public:
TitanicEngine(OSystem *syst, const TitanicGameDescription *gameDesc);
virtual ~TitanicEngine();
+
+ /**
+ * Returns true if a savegame can be loaded
+ */
+ virtual bool canLoadGameStateCurrently();
+
+ /**
+ * Returns true if the game can be saved
+ */
+ virtual bool canSaveGameStateCurrently();
+
+ /**
+ * Called by the GMM to load a savegame
+ */
+ virtual Common::Error loadGameState(int slot);
+
+ /**
+ * Called by the GMM to save the game
+ */
+ virtual Common::Error saveGameState(int slot, const Common::String &desc);
+
uint32 getFeatures() const;
bool isDemo() const;
Common::Language getLanguage() const;
@@ -141,6 +153,12 @@ public:
* Gets a random number
*/
uint getRandomNumber(uint max) { return _randomSource.getRandomNumber(max); }
+
+ /**
+ * Support method that generates a savegame name
+ * @param slot Slot number
+ */
+ CString generateSaveName(int slot);
};
extern TitanicEngine *g_vm;