Permalink
Browse files

MUTATIONOFJB: Basic save/load support.

Warning: The save format is subject to change.
  • Loading branch information...
LubomirR committed Aug 30, 2018
1 parent 041ab36 commit 543f7666f3577eb4cdfe7988873fa731b995d45b
@@ -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 @@ class MutationOfJBMetaEngine : public AdvancedMetaEngine {
_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 @@ class Game {
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);
}

}
Oops, something went wrong.

0 comments on commit 543f766

Please sign in to comment.