mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-19 00:15:30 +00:00
MUTATIONOFJB: Basic save/load support.
Warning: The save format is subject to change.
This commit is contained in:
parent
041ab36558
commit
543f7666f3
@ -23,6 +23,9 @@
|
||||
#include "mutationofjb/mutationofjb.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
@ -89,20 +92,59 @@ public:
|
||||
_directoryGlobs = mutationofjbDirectoryGlobs;
|
||||
}
|
||||
|
||||
virtual const char *getName() const {
|
||||
virtual const char *getName() const override {
|
||||
return "Mutation of J.B.";
|
||||
}
|
||||
|
||||
virtual const char *getOriginalCopyright() const {
|
||||
virtual const char *getOriginalCopyright() const override {
|
||||
return "Mutation of J.B. (C) 1996 RIKI Computer Games";
|
||||
}
|
||||
|
||||
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
|
||||
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override {
|
||||
if (desc) {
|
||||
*engine = new MutationOfJB::MutationOfJBEngine(syst);
|
||||
}
|
||||
return desc != nullptr;
|
||||
}
|
||||
|
||||
virtual bool hasFeature(MetaEngineFeature f) const override {
|
||||
if (f == kSupportsListSaves || f == kSimpleSavesNames) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual int getMaximumSaveSlot() const override {
|
||||
return 999;
|
||||
}
|
||||
|
||||
virtual SaveStateList listSaves(const char *target) const override {
|
||||
Common::SaveFileManager *const saveFileMan = g_system->getSavefileManager();
|
||||
Common::StringArray filenames;
|
||||
Common::String pattern = target;
|
||||
pattern += ".###";
|
||||
|
||||
filenames = saveFileMan->listSavefiles(pattern);
|
||||
|
||||
SaveStateList saveList;
|
||||
int slotNo = 0;
|
||||
for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
|
||||
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||
slotNo = atoi(file->c_str() + file->size() - 3);
|
||||
|
||||
Common::InSaveFile *const in = saveFileMan->openForLoading(*file);
|
||||
if (in) {
|
||||
Common::Serializer sz(in, nullptr);
|
||||
|
||||
MutationOfJB::SaveHeader saveHdr;
|
||||
if (saveHdr.sync(sz)) {
|
||||
saveList.push_back(SaveStateDescriptor(slotNo, saveHdr._description));
|
||||
}
|
||||
}
|
||||
}
|
||||
return saveList;
|
||||
}
|
||||
};
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(MUTATIONOFJB)
|
||||
|
@ -92,7 +92,7 @@ bool Game::loadGameData(bool partB) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_gameData->loadFromStream(file);
|
||||
_gameData->loadInitialState(file);
|
||||
|
||||
file.close();
|
||||
|
||||
@ -255,4 +255,14 @@ void Game::setActiveSayTask(const TaskPtr &sayTask) {
|
||||
_activeSayTask = sayTask;
|
||||
}
|
||||
|
||||
bool Game::loadSaveAllowed() const {
|
||||
if (_scriptExecCtx.isCommandRunning())
|
||||
return false;
|
||||
|
||||
if (isCurrentSceneMap())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -81,6 +81,8 @@ public:
|
||||
TaskPtr getActiveSayTask() const;
|
||||
void setActiveSayTask(const TaskPtr &sayTask);
|
||||
|
||||
bool loadSaveAllowed() const;
|
||||
|
||||
private:
|
||||
bool loadGameData(bool partB);
|
||||
void runActiveCommand();
|
||||
|
@ -21,12 +21,14 @@
|
||||
*/
|
||||
|
||||
#include "mutationofjb/gamedata.h"
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "common/stream.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
|
||||
static bool readString(Common::ReadStream &stream, char *str) {
|
||||
static bool readEntityNameString(Common::ReadStream &stream, char *str) {
|
||||
char buf[MAX_ENTITY_NAME_LENGTH];
|
||||
memset(str, 0, MAX_ENTITY_NAME_LENGTH + 1);
|
||||
|
||||
@ -39,12 +41,24 @@ static bool readString(Common::ReadStream &stream, char *str) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void syncEntityNameString(char *cstr, Common::Serializer &sz) {
|
||||
if (sz.isLoading()) {
|
||||
Common::String str;
|
||||
sz.syncString(str);
|
||||
strncpy(cstr, str.c_str(), MAX_ENTITY_NAME_LENGTH);
|
||||
cstr[MAX_ENTITY_NAME_LENGTH] = 0;
|
||||
} else {
|
||||
Common::String str(cstr);
|
||||
sz.syncString(str);
|
||||
}
|
||||
}
|
||||
|
||||
bool Door::isActive() {
|
||||
return *_name != '\0';
|
||||
}
|
||||
|
||||
bool Door::loadFromStream(Common::ReadStream &stream) {
|
||||
readString(stream, _name);
|
||||
bool Door::loadInitialState(Common::ReadStream &stream) {
|
||||
readEntityNameString(stream, _name);
|
||||
|
||||
_destSceneId = stream.readByte();
|
||||
_destX = stream.readUint16LE();
|
||||
@ -60,7 +74,21 @@ bool Door::loadFromStream(Common::ReadStream &stream) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Object::loadFromStream(Common::ReadStream &stream) {
|
||||
void Door::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
syncEntityNameString(_name, sz);
|
||||
sz.syncAsByte(_destSceneId);
|
||||
sz.syncAsUint16LE(_destX);
|
||||
sz.syncAsUint16LE(_destY);
|
||||
sz.syncAsUint16LE(_x);
|
||||
sz.syncAsByte(_y);
|
||||
sz.syncAsUint16LE(_width);
|
||||
sz.syncAsByte(_height);
|
||||
sz.syncAsUint16LE(_walkToX);
|
||||
sz.syncAsByte(_walkToY);
|
||||
sz.syncAsByte(_SP);
|
||||
}
|
||||
|
||||
bool Object::loadInitialState(Common::ReadStream &stream) {
|
||||
_active = stream.readByte();
|
||||
_firstFrame = stream.readByte();
|
||||
_randomFrame = stream.readByte();
|
||||
@ -79,9 +107,26 @@ bool Object::loadFromStream(Common::ReadStream &stream) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Static::loadFromStream(Common::ReadStream &stream) {
|
||||
void Object::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
sz.syncAsByte(_active);
|
||||
sz.syncAsByte(_firstFrame);
|
||||
sz.syncAsByte(_randomFrame);
|
||||
sz.syncAsByte(_numFrames);
|
||||
sz.syncAsByte(_roomFrameLSB);
|
||||
sz.syncAsByte(_jumpChance);
|
||||
sz.syncAsByte(_currentFrame);
|
||||
sz.syncAsUint16LE(_x);
|
||||
sz.syncAsByte(_y);
|
||||
sz.syncAsUint16LE(_width);
|
||||
sz.syncAsByte(_height);
|
||||
sz.syncAsUint16LE(_WX);
|
||||
sz.syncAsByte(_roomFrameMSB);
|
||||
sz.syncAsByte(_SP);
|
||||
}
|
||||
|
||||
bool Static::loadInitialState(Common::ReadStream &stream) {
|
||||
_active = stream.readByte();
|
||||
readString(stream, _name);
|
||||
readEntityNameString(stream, _name);
|
||||
_x = stream.readUint16LE();
|
||||
_y = stream.readByte();
|
||||
_width = stream.readUint16LE();
|
||||
@ -93,7 +138,19 @@ bool Static::loadFromStream(Common::ReadStream &stream) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bitmap::loadFromStream(Common::ReadStream &stream) {
|
||||
void Static::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
sz.syncAsByte(_active);
|
||||
syncEntityNameString(_name, sz);
|
||||
sz.syncAsUint16LE(_x);
|
||||
sz.syncAsByte(_y);
|
||||
sz.syncAsUint16LE(_width);
|
||||
sz.syncAsByte(_height);
|
||||
sz.syncAsUint16LE(_walkToX);
|
||||
sz.syncAsByte(_walkToY);
|
||||
sz.syncAsByte(_walkToFrame);
|
||||
}
|
||||
|
||||
bool Bitmap::loadInitialState(Common::ReadStream &stream) {
|
||||
_roomFrame = stream.readByte();
|
||||
_isVisible = stream.readByte();
|
||||
_x1 = stream.readUint16LE();
|
||||
@ -104,7 +161,16 @@ bool Bitmap::loadFromStream(Common::ReadStream &stream) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Scene::loadFromStream(Common::ReadStream &stream) {
|
||||
void Bitmap::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
sz.syncAsByte(_roomFrame);
|
||||
sz.syncAsByte(_isVisible);
|
||||
sz.syncAsUint16LE(_x1);
|
||||
sz.syncAsByte(_y1);
|
||||
sz.syncAsUint16LE(_x2);
|
||||
sz.syncAsByte(_y2);
|
||||
}
|
||||
|
||||
bool Scene::loadInitialState(Common::ReadStream &stream) {
|
||||
int i;
|
||||
|
||||
_startup = stream.readByte();
|
||||
@ -116,23 +182,23 @@ bool Scene::loadFromStream(Common::ReadStream &stream) {
|
||||
_noDoors = stream.readByte();
|
||||
_noDoors = MIN(_noDoors, static_cast<uint8>(ARRAYSIZE(_doors)));
|
||||
for (i = 0; i < ARRAYSIZE(_doors); ++i) {
|
||||
_doors[i].loadFromStream(stream);
|
||||
_doors[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
_noObjects = stream.readByte();
|
||||
_noObjects = MIN(_noObjects, static_cast<uint8>(ARRAYSIZE(_objects)));
|
||||
for (i = 0; i < ARRAYSIZE(_objects); ++i) {
|
||||
_objects[i].loadFromStream(stream);
|
||||
_objects[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
_noStatics = stream.readByte();
|
||||
_noStatics = MIN(_noStatics, static_cast<uint8>(ARRAYSIZE(_statics)));
|
||||
for (i = 0; i < ARRAYSIZE(_statics); ++i) {
|
||||
_statics[i].loadFromStream(stream);
|
||||
_statics[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAYSIZE(_bitmaps); ++i) {
|
||||
_bitmaps[i].loadFromStream(stream);
|
||||
_bitmaps[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
_obstacleY1 = stream.readUint16LE();
|
||||
@ -141,13 +207,50 @@ bool Scene::loadFromStream(Common::ReadStream &stream) {
|
||||
_palRotDelay = stream.readByte();
|
||||
_exhaustedConvItemNext = stream.readByte();
|
||||
|
||||
for (i = 0; i < 79; ++i) {
|
||||
for (i = 0; i < ARRAYSIZE(_exhaustedConvItems); ++i) {
|
||||
_exhaustedConvItems[i]._encodedData = stream.readByte();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Scene::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
sz.syncAsByte(_startup);
|
||||
sz.syncAsByte(_unknown001);
|
||||
sz.syncAsByte(_unknown002);
|
||||
sz.syncAsByte(_unknown003);
|
||||
sz.syncAsByte(_delay);
|
||||
|
||||
sz.syncAsByte(_noDoors);
|
||||
for (int i = 0; i < ARRAYSIZE(_doors); ++i) {
|
||||
_doors[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
sz.syncAsByte(_noObjects);
|
||||
for (int i = 0; i < ARRAYSIZE(_objects); ++i) {
|
||||
_objects[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
sz.syncAsByte(_noStatics);
|
||||
for (int i = 0; i < ARRAYSIZE(_statics); ++i) {
|
||||
_statics[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(_bitmaps); ++i) {
|
||||
_bitmaps[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
sz.syncAsUint16LE(_obstacleY1);
|
||||
sz.syncAsByte(_palRotFirst);
|
||||
sz.syncAsByte(_palRotLast);
|
||||
sz.syncAsByte(_palRotDelay);
|
||||
sz.syncAsByte(_exhaustedConvItemNext);
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(_exhaustedConvItems); ++i) {
|
||||
sz.syncAsByte(_exhaustedConvItems[i]._encodedData);
|
||||
}
|
||||
}
|
||||
|
||||
Door *Scene::getDoor(uint8 doorId) {
|
||||
if (doorId == 0 || doorId > _noDoors) {
|
||||
warning("Door %d does not exist", doorId);
|
||||
@ -270,12 +373,23 @@ Inventory &GameData::getInventory() {
|
||||
return _inventory;
|
||||
}
|
||||
|
||||
bool GameData::loadFromStream(Common::ReadStream &stream) {
|
||||
bool GameData::loadInitialState(Common::ReadStream &stream) {
|
||||
for (int i = 0; i < ARRAYSIZE(_scenes); ++i) {
|
||||
_scenes[i].loadFromStream(stream);
|
||||
_scenes[i].loadInitialState(stream);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameData::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
for (int i = 0; i < ARRAYSIZE(_scenes); ++i) {
|
||||
_scenes[i].saveLoadWithSerializer(sz);
|
||||
}
|
||||
|
||||
sz.syncAsByte(_currentScene);
|
||||
sz.syncAsByte(_partB);
|
||||
_inventory.saveLoadWithSerializer(sz);
|
||||
sz.syncString(_currentAPK);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,9 +23,11 @@
|
||||
#ifndef MUTATIONOFJB_GAMEDATA_H
|
||||
#define MUTATIONOFJB_GAMEDATA_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "mutationofjb/inventory.h"
|
||||
|
||||
#include "common/serializer.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Common {
|
||||
class ReadStream;
|
||||
}
|
||||
@ -36,7 +38,7 @@ enum {
|
||||
MAX_ENTITY_NAME_LENGTH = 0x14
|
||||
};
|
||||
|
||||
/** @file gamedata.h
|
||||
/** @file
|
||||
* There are 4 types of entities present in the game data:
|
||||
* - Door
|
||||
* - Object
|
||||
@ -47,7 +49,9 @@ enum {
|
||||
/**
|
||||
* An interactable scene changer with no visual representation.
|
||||
*/
|
||||
struct Door {
|
||||
struct Door : public Common::Serializable {
|
||||
virtual ~Door() {}
|
||||
|
||||
/**
|
||||
* Door name (NM register).
|
||||
*
|
||||
@ -80,7 +84,7 @@ struct Door {
|
||||
uint16 _walkToX;
|
||||
/** Y coordinate for position player will walk towards after clicking the door (WY register). */
|
||||
uint8 _walkToY;
|
||||
/* Unknown for now - likely not even used. */
|
||||
/** Unknown for now - likely not even used. */
|
||||
uint8 _SP;
|
||||
|
||||
/**
|
||||
@ -89,7 +93,20 @@ struct Door {
|
||||
*/
|
||||
bool isActive();
|
||||
|
||||
bool loadFromStream(Common::ReadStream &stream);
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -105,7 +122,7 @@ struct Door {
|
||||
*
|
||||
* For details regarding animation playback, see objectanimationtask.cpp.
|
||||
*/
|
||||
struct Object {
|
||||
struct Object : public Common::Serializable {
|
||||
/** Controls whether the animation is playing. */
|
||||
uint8 _active;
|
||||
/**
|
||||
@ -163,16 +180,29 @@ struct Object {
|
||||
* @see _roomFrameLSB
|
||||
*/
|
||||
uint8 _roomFrameMSB;
|
||||
/* Unknown. TODO: Figure out what this does. */
|
||||
/** Unknown. TODO: Figure out what this does. */
|
||||
uint8 _SP;
|
||||
|
||||
bool loadFromStream(Common::ReadStream &stream);
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* An interactable area, usually without a visual representation.
|
||||
*/
|
||||
struct Static {
|
||||
struct Static : public Common::Serializable {
|
||||
/** Whether you can mouse over and interact with the static (AC register). */
|
||||
uint8 _active;
|
||||
/**
|
||||
@ -206,14 +236,27 @@ struct Static {
|
||||
/** Player frame (rotation) set after the player finishes walking towards the walk to position (SP register). */
|
||||
uint8 _walkToFrame;
|
||||
|
||||
bool loadFromStream(Common::ReadStream &stream);
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* A static image that is carved out of a room frame based on its rectangle.
|
||||
* The bitmap rectangle also specifies where to blit it on the screen.
|
||||
*/
|
||||
struct Bitmap {
|
||||
struct Bitmap : public Common::Serializable {
|
||||
/** Room frame that this bitmap carves out of. */
|
||||
uint8 _roomFrame;
|
||||
/** Whether to draw the bitmap. */
|
||||
@ -227,7 +270,20 @@ struct Bitmap {
|
||||
/** Y coordinate of the bottom right corner of the bitmap rectangle. */
|
||||
uint8 _y2;
|
||||
|
||||
bool loadFromStream(Common::ReadStream &stream);
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -256,7 +312,7 @@ struct ExhaustedConvItem {
|
||||
_encodedData(((context & 0x1) << 7) | ((convItemIndex & 0x7) << 4) | (convGroupIndex & 0xF)) {}
|
||||
};
|
||||
|
||||
struct Scene {
|
||||
struct Scene : Common::Serializable {
|
||||
Door *getDoor(uint8 objectId);
|
||||
Object *getObject(uint8 objectId, bool ignoreNo = false);
|
||||
Static *getStatic(uint8 staticId, bool ignoreNo = false);
|
||||
@ -328,7 +384,20 @@ struct Scene {
|
||||
uint8 _exhaustedConvItemNext;
|
||||
ExhaustedConvItem _exhaustedConvItems[79];
|
||||
|
||||
bool loadFromStream(Common::ReadStream &stream);
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
};
|
||||
|
||||
struct ConversationInfo {
|
||||
@ -346,14 +415,27 @@ struct ConversationInfo {
|
||||
uint8 _color;
|
||||
};
|
||||
|
||||
struct GameData {
|
||||
struct GameData : public Common::Serializable {
|
||||
public:
|
||||
GameData();
|
||||
Scene *getScene(uint8 sceneId);
|
||||
Scene *getCurrentScene();
|
||||
Inventory &getInventory();
|
||||
|
||||
bool loadFromStream(Common::ReadStream &stream);
|
||||
/**
|
||||
* Load initial state from game data file.
|
||||
*
|
||||
* @param stream Stream for reading.
|
||||
* @return True if success, false otherwise.
|
||||
*/
|
||||
bool loadInitialState(Common::ReadStream &stream);
|
||||
|
||||
/**
|
||||
* (De)serialization for save/load.
|
||||
*
|
||||
* @param sz Serializer.
|
||||
*/
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
|
||||
uint8 _currentScene; // Persistent.
|
||||
uint8 _lastScene;
|
||||
|
@ -137,4 +137,21 @@ void Inventory::reverseItems(uint from, uint to) {
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory::saveLoadWithSerializer(Common::Serializer &sz) {
|
||||
if (sz.isLoading()) {
|
||||
uint32 length = 0;
|
||||
sz.syncAsUint32LE(length);
|
||||
if (length) {
|
||||
_items.resize(length);
|
||||
}
|
||||
} else {
|
||||
uint32 length = static_cast<uint32>(_items.size());
|
||||
sz.syncAsUint32LE(length);
|
||||
}
|
||||
|
||||
for (Items::size_type i = 0; i < _items.size(); ++i) {
|
||||
sz.syncString(_items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,8 +23,9 @@
|
||||
#ifndef MUTATIONOFJB_INVENTORY_H
|
||||
#define MUTATIONOFJB_INVENTORY_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/array.h"
|
||||
#include "common/serializer.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/str.h"
|
||||
|
||||
namespace MutationOfJB {
|
||||
@ -37,7 +38,7 @@ public:
|
||||
virtual ~InventoryObserver() {}
|
||||
};
|
||||
|
||||
class Inventory {
|
||||
class Inventory : public Common::Serializable {
|
||||
public:
|
||||
enum {
|
||||
VISIBLE_ITEMS = 6
|
||||
@ -59,6 +60,8 @@ public:
|
||||
|
||||
void setObserver(InventoryObserver *observer);
|
||||
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &sz) override;
|
||||
|
||||
private:
|
||||
void rotateItemsRight(uint n);
|
||||
void rotateItemsLeft(uint n);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "common/system.h"
|
||||
#include "common/events.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/savefile.h"
|
||||
#include "graphics/screen.h"
|
||||
#include "graphics/cursorman.h"
|
||||
|
||||
@ -125,6 +126,55 @@ void MutationOfJBEngine::updateCursor() {
|
||||
}
|
||||
}
|
||||
|
||||
bool MutationOfJBEngine::hasFeature(Engine::EngineFeature f) const {
|
||||
if (f == kSupportsLoadingDuringRuntime || f == kSupportsSavingDuringRuntime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MutationOfJBEngine::canLoadGameStateCurrently() {
|
||||
return _game->loadSaveAllowed();
|
||||
}
|
||||
|
||||
Common::Error MutationOfJBEngine::loadGameState(int slot) {
|
||||
const Common::String saveName = Common::String::format("%s.%03d", _targetName.c_str(), slot);
|
||||
Common::InSaveFile *const saveFile = g_system->getSavefileManager()->openForLoading(saveName);
|
||||
|
||||
Common::Serializer sz(saveFile, nullptr);
|
||||
|
||||
SaveHeader saveHdr;
|
||||
saveHdr.sync(sz);
|
||||
_game->getGameData().saveLoadWithSerializer(sz);
|
||||
delete saveFile;
|
||||
|
||||
_game->changeScene(_game->getGameData()._currentScene, _game->getGameData()._partB);
|
||||
_game->getGui().markDirty();
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool MutationOfJBEngine::canSaveGameStateCurrently() {
|
||||
return _game->loadSaveAllowed();
|
||||
}
|
||||
|
||||
Common::Error MutationOfJBEngine::saveGameState(int slot, const Common::String &desc) {
|
||||
const Common::String saveName = Common::String::format("%s.%03d", _targetName.c_str(), slot);
|
||||
Common::OutSaveFile *const saveFile = g_system->getSavefileManager()->openForSaving(saveName);
|
||||
|
||||
Common::Serializer sz(nullptr, saveFile);
|
||||
|
||||
SaveHeader saveHdr;
|
||||
saveHdr._description = desc;
|
||||
saveHdr.sync(sz);
|
||||
_game->getGameData().saveLoadWithSerializer(sz);
|
||||
saveFile->finalize();
|
||||
delete saveFile;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
void MutationOfJBEngine::handleNormalScene(const Common::Event &event) {
|
||||
Scene *const scene = _game->getGameData().getCurrentScene();
|
||||
|
||||
@ -255,6 +305,9 @@ Common::Error MutationOfJBEngine::run() {
|
||||
event.kbd.ascii == '~' || event.kbd.ascii == '#') {
|
||||
_console->attach();
|
||||
}
|
||||
if (event.kbd.keycode == Common::KEYCODE_F5 && event.kbd.hasFlags(0)) {
|
||||
openMainMenuDialog();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Common::EVENT_KEYUP: {
|
||||
@ -297,4 +350,26 @@ Common::Error MutationOfJBEngine::run() {
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool SaveHeader::sync(Common::Serializer &sz) {
|
||||
const uint32 SAVE_MAGIC_NUMBER = MKTAG('M', 'O', 'J', 'B');
|
||||
const uint32 SAVE_FILE_VERSION = 1;
|
||||
|
||||
if (sz.isLoading()) {
|
||||
uint32 magic = 0;
|
||||
sz.syncAsUint32BE(magic);
|
||||
if (magic != SAVE_MAGIC_NUMBER) {
|
||||
warning("Invalid save");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
uint32 magic = SAVE_MAGIC_NUMBER;
|
||||
sz.syncAsUint32BE(magic);
|
||||
}
|
||||
|
||||
sz.syncVersion(SAVE_FILE_VERSION);
|
||||
sz.syncString(_description);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
namespace Common {
|
||||
struct Event;
|
||||
class Serializer;
|
||||
}
|
||||
|
||||
namespace Graphics {
|
||||
@ -39,6 +40,12 @@ namespace MutationOfJB {
|
||||
class Console;
|
||||
class Game;
|
||||
|
||||
struct SaveHeader {
|
||||
bool sync(Common::Serializer &sz);
|
||||
|
||||
Common::String _description;
|
||||
};
|
||||
|
||||
class MutationOfJBEngine : public Engine {
|
||||
public:
|
||||
enum CursorState {
|
||||
@ -56,6 +63,12 @@ public:
|
||||
void setCursorState(CursorState cursorState);
|
||||
void updateCursor();
|
||||
|
||||
virtual bool hasFeature(EngineFeature f) const override;
|
||||
virtual bool canLoadGameStateCurrently() override;
|
||||
virtual Common::Error loadGameState(int slot) override;
|
||||
virtual bool canSaveGameStateCurrently() override;
|
||||
virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
|
||||
|
||||
private:
|
||||
bool loadGameData(bool partB);
|
||||
void setupCursor();
|
||||
|
@ -207,6 +207,10 @@ Command *ScriptExecutionContext::getExtra(const Common::String &name) const {
|
||||
return cmd;
|
||||
}
|
||||
|
||||
bool ScriptExecutionContext::isCommandRunning() const {
|
||||
return _activeCommand;
|
||||
}
|
||||
|
||||
bool Script::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
destroy();
|
||||
|
||||
|
@ -119,6 +119,7 @@ public:
|
||||
GameData &getGameData();
|
||||
Command *getMacro(const Common::String &name) const;
|
||||
Command *getExtra(const Common::String &name) const;
|
||||
bool isCommandRunning() const;
|
||||
|
||||
private:
|
||||
Game &_game;
|
||||
|
Loading…
x
Reference in New Issue
Block a user