aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2011-09-16 09:20:41 -0400
committerMatthew Hoops2011-09-16 09:20:41 -0400
commit2ae8a97c4d915b04e9824f2478812041e4c088f0 (patch)
treee6ba8803ab09e923e8fc5d5205baa079381bedbf
parentecde87260c1db0de463f294b551402c08e731d0e (diff)
downloadscummvm-rg350-2ae8a97c4d915b04e9824f2478812041e4c088f0.tar.gz
scummvm-rg350-2ae8a97c4d915b04e9824f2478812041e4c088f0.tar.bz2
scummvm-rg350-2ae8a97c4d915b04e9824f2478812041e4c088f0.zip
PEGASUS: Stub off loading/saving games
-rwxr-xr-xengines/pegasus/constants.h17
-rw-r--r--engines/pegasus/detection.cpp40
-rw-r--r--engines/pegasus/pegasus.cpp148
-rw-r--r--engines/pegasus/pegasus.h23
4 files changed, 223 insertions, 5 deletions
diff --git a/engines/pegasus/constants.h b/engines/pegasus/constants.h
index dd12727baf..b9b8540663 100755
--- a/engines/pegasus/constants.h
+++ b/engines/pegasus/constants.h
@@ -26,6 +26,8 @@
#ifndef PEGASUS_CONSTANTS_H
#define PEGASUS_CONSTANTS_H
+#include "common/endian.h"
+
#include "pegasus/types.h"
namespace Pegasus {
@@ -247,6 +249,21 @@ const tNotificationFlags kNeighborhoodFlags = kNeighborhoodMovieCompletedFlag |
kActionRequestCompletedFlag |
kDeathExtraCompletedFlag;
+const uint32 kPegasusPrimeCreator = MKTAG('J', 'P', 'P', 'P');
+const uint32 kPegasusPrimeContinueType = MKTAG('P', 'P', 'C', 'T');
+
+const uint32 kPegasusPrimeDisk1GameType = MKTAG('P', 'P', 'G', '1');
+const uint32 kPegasusPrimeDisk2GameType = MKTAG('P', 'P', 'G', '2');
+const uint32 kPegasusPrimeDisk3GameType = MKTAG('P', 'P', 'G', '3');
+const uint32 kPegasusPrimeDisk4GameType = MKTAG('P', 'P', 'G', '4');
+
+// We only support one of the save versions; the rest are from betas
+// and we are not supporting them.
+const uint32 kPegasusPrimeVersion = 0x00009019;
+
+const char kNormalSave = 0;
+const char kContinueSave = 1;
+
} // End of namespace Pegasus
#endif
diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp
index 9c486f7548..af651c8f22 100644
--- a/engines/pegasus/detection.cpp
+++ b/engines/pegasus/detection.cpp
@@ -25,6 +25,7 @@
#include "engines/advancedDetector.h"
#include "common/config-manager.h"
#include "common/file.h"
+#include "common/savefile.h"
#include "pegasus/pegasus.h"
@@ -36,7 +37,9 @@ struct PegasusGameDescription {
bool PegasusEngine::hasFeature(EngineFeature f) const {
return
- (f == kSupportsRTL);
+ (f == kSupportsRTL)
+ || (f == kSupportsLoadingDuringRuntime)
+ || (f == kSupportsSavingDuringRuntime);
}
bool PegasusEngine::isDemo() const {
@@ -98,9 +101,44 @@ public:
return "The Journeyman Project: Pegasus Prime (C) Presto Studios";
}
+ virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+ virtual SaveStateList listSaves(const char *target) const;
+ virtual int getMaximumSaveSlot() const { return 999; }
+ virtual void removeSaveState(const char *target, int slot) const;
};
+bool PegasusMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return
+ (f == kSupportsListSaves)
+ || (f == kSupportsDeleteSave);
+}
+
+SaveStateList PegasusMetaEngine::listSaves(const char *target) const {
+ // The original had no pattern, so the user must rename theirs
+ // Note that we ignore the target because saves are compatible between
+ // all versions
+ Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("pegasus-*.sav");
+
+ SaveStateList saveList;
+ for (uint32 i = 0; i < filenames.size(); i++) {
+ // Isolate the description from the file name
+ Common::String desc = filenames[i].c_str() + 8;
+ for (int j = 0; j < 4; j++)
+ desc.deleteLastChar();
+
+ saveList.push_back(SaveStateDescriptor(i, desc));
+ }
+
+ return saveList;
+}
+
+void PegasusMetaEngine::removeSaveState(const char *target, int slot) const {
+ // See listSaves() for info on the pattern
+ Common::StringArray filenames = g_system->getSavefileManager()->listSavefiles("pegasus-*.sav");
+ g_system->getSavefileManager()->removeSavefile(filenames[slot].c_str());
+}
+
bool PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
const Pegasus::PegasusGameDescription *gd = (const Pegasus::PegasusGameDescription *)desc;
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index dacc2a0a30..3a9c7d1a5f 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -25,6 +25,8 @@
#include "common/events.h"
#include "common/file.h"
#include "common/fs.h"
+#include "common/memstream.h"
+#include "common/savefile.h"
#include "common/textconsole.h"
#include "common/translation.h"
#include "base/plugins.h"
@@ -36,6 +38,7 @@
#include "pegasus/gamestate.h"
#include "pegasus/pegasus.h"
#include "pegasus/timers.h"
+#include "pegasus/items/itemlist.h"
#include "pegasus/items/biochips/biochipitem.h"
#include "pegasus/items/inventory/inventoryitem.h"
@@ -49,6 +52,8 @@
namespace Pegasus {
PegasusEngine::PegasusEngine(OSystem *syst, const PegasusGameDescription *gamedesc) : Engine(syst), InputHandler(0), _gameDescription(gamedesc) {
+ _continuePoint = 0;
+ _saveAllowed = _loadAllowed = true;
}
PegasusEngine::~PegasusEngine() {
@@ -59,6 +64,7 @@ PegasusEngine::~PegasusEngine() {
delete _biochipLid;
delete _console;
delete _cursor;
+ delete _continuePoint;
}
Common::Error PegasusEngine::run() {
@@ -340,4 +346,146 @@ void PegasusEngine::removeTimeBase(TimeBase *timeBase) {
_timeBases.remove(timeBase);
}
+bool PegasusEngine::loadFromStream(Common::ReadStream *stream) {
+ // TODO: Dispose currently running stuff (neighborhood, etc.)
+
+ // Signature
+ uint32 creator = stream->readUint32BE();
+ if (creator != kPegasusPrimeCreator) {
+ warning("Bad save creator '%s'", tag2str(creator));
+ return false;
+ }
+
+ uint32 gameType = stream->readUint32BE();
+ int saveType;
+
+ switch (gameType) {
+ case kPegasusPrimeDisk1GameType:
+ case kPegasusPrimeDisk2GameType:
+ case kPegasusPrimeDisk3GameType:
+ case kPegasusPrimeDisk4GameType:
+ saveType = kNormalSave;
+ break;
+ case kPegasusPrimeContinueType:
+ saveType = kContinueSave;
+ break;
+ default:
+ // There are five other possible game types on the Pippin
+ // version, but hopefully we don't see any of those here
+ warning("Unhandled pegasus game type '%s'", tag2str(gameType));
+ return false;
+ }
+
+ uint32 version = stream->readUint32BE();
+ if (version != kPegasusPrimeVersion) {
+ warning("Where did you get this save? It's a beta (v%04x)!", version & 0x7fff);
+ return false;
+ }
+
+ // Game State
+ GameState.readGameState(stream);
+
+ // TODO: Energy
+ stream->readUint32BE();
+
+ // TODO: Death reason
+ stream->readByte();
+
+ // TODO: This is as far as we can go right now
+ return true;
+
+ // Items
+ g_allItems.readFromStream(stream);
+
+ // TODO: Player Inventory
+ // TODO: Player BioChips
+ // TODO: Disc check
+ // TODO: Jump to environment
+ // TODO: AI rules
+
+ // Make a new continue point if this isn't already one
+ if (saveType == kNormalSave)
+ makeContinuePoint();
+
+ return true;
+}
+
+bool PegasusEngine::writeToStream(Common::WriteStream *stream, int saveType) {
+ // Not ready yet! :P
+ return false;
+
+ // Signature
+ stream->writeUint32BE(kPegasusPrimeCreator);
+
+ if (saveType == kNormalSave) {
+ // TODO: Disc check
+ stream->writeUint32BE(kPegasusPrimeDisk1GameType);
+ } else { // Continue
+ stream->writeUint32BE(kPegasusPrimeContinueType);
+ }
+
+ stream->writeUint32BE(kPegasusPrimeVersion);
+
+ // Game State
+ GameState.writeGameState(stream);
+
+ // TODO: Energy
+ stream->writeUint32BE(0);
+
+ // TODO: Death reason
+ stream->writeByte(0);
+
+ // Items
+ g_allItems.writeToStream(stream);
+
+ // TODO: Player Inventory
+ // TODO: Player BioChips
+ // TODO: Jump to environment
+ // TODO: AI rules
+ return true;
+}
+
+void PegasusEngine::makeContinuePoint() {
+ delete _continuePoint;
+
+ Common::MemoryWriteStreamDynamic newPoint(DisposeAfterUse::NO);
+ writeToStream(&newPoint, kContinueSave);
+ _continuePoint = new Common::MemoryReadStream(newPoint.getData(), newPoint.size(), DisposeAfterUse::YES);
+}
+
+void PegasusEngine::loadFromContinuePoint() {
+ // Failure to load a continue point is fatal
+
+ if (!_continuePoint)
+ error("Attempting to load from non-existant continue point");
+
+ if (!loadFromStream(_continuePoint))
+ error("Failed loading continue point");
+}
+
+Common::Error PegasusEngine::loadGameState(int slot) {
+ Common::StringArray filenames = _saveFileMan->listSavefiles("pegasus-*.sav");
+ Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filenames[slot]);
+ if (!loadFile)
+ return Common::kUnknownError;
+
+ bool valid = loadFromStream(loadFile);
+ warning("pos = %d", loadFile->pos());
+ delete loadFile;
+
+ return valid ? Common::kNoError : Common::kUnknownError;
+}
+
+Common::Error PegasusEngine::saveGameState(int slot, const Common::String &desc) {
+ Common::String output = Common::String::format("pegasus-%s.sav", desc.c_str());
+ Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(output);
+ if (!saveFile)
+ return Common::kUnknownError;
+
+ bool valid = writeToStream(saveFile, kNormalSave);
+ delete saveFile;
+
+ return valid ? Common::kNoError : Common::kUnknownError;
+}
+
} // End of namespace Pegasus
diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h
index 5074aaba09..8d49050ab6 100644
--- a/engines/pegasus/pegasus.h
+++ b/engines/pegasus/pegasus.h
@@ -72,22 +72,29 @@ friend class InputHandler;
public:
PegasusEngine(OSystem *syst, const PegasusGameDescription *gamedesc);
virtual ~PegasusEngine();
-
+
+ // Engine stuff
const PegasusGameDescription *_gameDescription;
bool hasFeature(EngineFeature f) const;
GUI::Debugger *getDebugger();
-
+ bool canLoadGameStateCurrently() { return _loadAllowed; }
+ bool canSaveGameStateCurrently() { return _saveAllowed; }
+ Common::Error loadGameState(int slot);
+ Common::Error saveGameState(int slot, const Common::String &desc);
+
+ // Base classes
VideoManager *_video;
GraphicsManager *_gfx;
Common::MacResManager *_resFork, *_inventoryLid, *_biochipLid;
+ // Misc.
bool isDemo() const;
-
void addIdler(Idler *idler);
void removeIdler(Idler *idler);
-
void addTimeBase(TimeBase *timeBase);
void removeTimeBase(TimeBase *timeBase);
+ void swapSaveAllowed(bool allow) { _saveAllowed = allow; }
+ void swapLoadAllowed(bool allow) { _loadAllowed = allow; }
protected:
Common::Error run();
@@ -148,6 +155,14 @@ private:
// TimeBases
Common::List<TimeBase *> _timeBases;
+
+ // Save/Load
+ bool loadFromStream(Common::ReadStream *stream);
+ bool writeToStream(Common::WriteStream *stream, int saveType);
+ void makeContinuePoint();
+ void loadFromContinuePoint();
+ Common::ReadStream *_continuePoint;
+ bool _saveAllowed, _loadAllowed; // It's so nice that this was in the original code already :P
};
} // End of namespace Pegasus