aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorĽubomír Remák2018-02-26 23:52:13 +0100
committerEugene Sandulenko2018-08-25 23:12:01 +0200
commit6d926ff55b2fccbf8e96495f88b3d4dda6e906d7 (patch)
treec2374f1fda58e18b86c0c9b612ae3988bc5b21ac /engines
parent3672ea55720666acfd64b6df01b35d0727d6be78 (diff)
downloadscummvm-rg350-6d926ff55b2fccbf8e96495f88b3d4dda6e906d7.tar.gz
scummvm-rg350-6d926ff55b2fccbf8e96495f88b3d4dda6e906d7.tar.bz2
scummvm-rg350-6d926ff55b2fccbf8e96495f88b3d4dda6e906d7.zip
MUTATIONOFJB: Add support for CHANGED, CHANGEO and CHANGES commands.
Diffstat (limited to 'engines')
-rw-r--r--engines/mutationofjb/commands/changecommand.cpp334
-rw-r--r--engines/mutationofjb/commands/changecommand.h120
-rw-r--r--engines/mutationofjb/commands/command.h2
-rw-r--r--engines/mutationofjb/commands/ifcommand.cpp2
-rw-r--r--engines/mutationofjb/commands/seqcommand.h1
-rw-r--r--engines/mutationofjb/game.cpp18
-rw-r--r--engines/mutationofjb/game.h2
-rw-r--r--engines/mutationofjb/module.mk1
-rw-r--r--engines/mutationofjb/script.cpp5
9 files changed, 482 insertions, 3 deletions
diff --git a/engines/mutationofjb/commands/changecommand.cpp b/engines/mutationofjb/commands/changecommand.cpp
new file mode 100644
index 0000000000..54c6d1e616
--- /dev/null
+++ b/engines/mutationofjb/commands/changecommand.cpp
@@ -0,0 +1,334 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mutationofjb/commands/changecommand.h"
+#include "common/translation.h"
+
+namespace MutationOfJB {
+
+// CHANGEe rr ss ii val
+// <e> 1B Entity to change register for.
+// D door
+// O object
+// S static
+// <rr> 2B Register name.
+// <ss> 2B Scene ID.
+// <ii> 2B Entity ID.
+// <val> VL Value.
+
+bool ChangeCommandParser::parseValueString(const Common::String &valueString, uint8 &sceneId, uint8 &entityId, ChangeCommand::ChangeRegister &reg, ChangeCommand::ChangeOperation &op, ChangeCommandValue &ccv) {
+ if (valueString.size() < 8) {
+ return false;
+ }
+
+ sceneId = atoi(valueString.c_str() + 3);
+ entityId = atoi(valueString.c_str() + 6);
+ const char *val = nullptr;
+ if (valueString.size() >= 9) {
+ val = valueString.c_str() + 9;
+ }
+
+ if (valueString.hasPrefix("NM")) {
+ reg = ChangeCommand::NM;
+ op = ChangeCommand::SetValue;
+ strncpy(ccv._strVal, val, MAX_STR_LENGTH);
+ } else if (valueString.hasPrefix("LT")) {
+ reg = ChangeCommand::LT;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("SX")) {
+ reg = ChangeCommand::SX;
+ ccv._wordVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("SY")) {
+ reg = ChangeCommand::SY;
+ ccv._wordVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("XX")) {
+ reg = ChangeCommand::XX;
+ ccv._wordVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("YY")) {
+ reg = ChangeCommand::YY;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("XL")) {
+ reg = ChangeCommand::XL;
+ ccv._wordVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("YL")) {
+ reg = ChangeCommand::YL;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("WX")) {
+ reg = ChangeCommand::WX;
+ ccv._wordVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("WY")) {
+ reg = ChangeCommand::WY;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("AC")) {
+ reg = ChangeCommand::AC;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("FA")) {
+ reg = ChangeCommand::FA;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("FR")) {
+ reg = ChangeCommand::FR;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("NA")) {
+ reg = ChangeCommand::NA;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("FS")) {
+ reg = ChangeCommand::FS;
+ ccv._byteVal = parseInteger(val, op);
+ } else if (valueString.hasPrefix("CA")) {
+ reg = ChangeCommand::CA;
+ ccv._byteVal = parseInteger(val, op);
+ }
+
+ return true;
+}
+
+
+bool ChangeDoorCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
+ if (!line.hasPrefix("CHANGED ")) {
+ return false;
+ }
+ uint8 sceneId = 0;
+ uint8 objectId = 0;
+ ChangeCommand::ChangeRegister reg;
+ ChangeCommand::ChangeOperation op;
+ ChangeCommandValue val;
+ if (!parseValueString(line.c_str() + 8, sceneId, objectId, reg, op, val)) {
+ return false;
+ }
+
+ command = new ChangeObjectCommand(sceneId, objectId, reg, op, val);
+ return true;
+}
+
+bool ChangeObjectCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
+ if (!line.hasPrefix("CHANGEO ")) {
+ return false;
+ }
+ uint8 sceneId = 0;
+ uint8 objectId = 0;
+ ChangeCommand::ChangeRegister reg;
+ ChangeCommand::ChangeOperation op;
+ ChangeCommandValue val;
+ if (!parseValueString(line.c_str() + 8, sceneId, objectId, reg, op, val)) {
+ return false;
+ }
+
+ command = new ChangeObjectCommand(sceneId, objectId, reg, op, val);
+ return true;
+}
+
+bool ChangeStaticCommandParser::parse(const Common::String &line, ScriptParseContext &, Command *&command) {
+ if (!line.hasPrefix("CHANGES ")) {
+ return false;
+ }
+ uint8 sceneId = 0;
+ uint8 objectId = 0;
+ ChangeCommand::ChangeRegister reg;
+ ChangeCommand::ChangeOperation op;
+ ChangeCommandValue val;
+ if (!parseValueString(line.c_str() + 8, sceneId, objectId, reg, op, val)) {
+ return false;
+ }
+
+ command = new ChangeObjectCommand(sceneId, objectId, reg, op, val);
+ return true;
+}
+
+int ChangeCommandParser::parseInteger(const char *val, ChangeCommand::ChangeOperation &op) {
+ if (!val || !(*val)) {
+ op = ChangeCommand::SetValue;
+ return 0;
+ }
+
+ if (val[0] == '\\') {
+ op = ChangeCommand::SetValue;
+ val++;
+ } else if (val[0] == '+') {
+ op = ChangeCommand::AddValue;
+ val++;
+ } else if (val[0] == '-') {
+ op = ChangeCommand::SubtractValue;
+ val++;
+ }
+
+ return atoi(val);
+}
+
+Command::ExecuteResult ChangeDoorCommand::execute(GameData &gameData) {
+ Scene *const scene = gameData.getScene(_sceneId);
+ if (!scene) {
+ return Finished;
+ }
+
+ Door *const door = scene->getDoor(_entityId);
+ if (!door) {
+ return Finished;
+ }
+
+ switch (_register) {
+ case NM:
+ strncpy(door->_name, _value._strVal, MAX_STR_LENGTH);
+ break;
+ case LT:
+ door->_destSceneId = _value._byteVal;
+ break;
+ case SX:
+ door->_destX = _value._wordVal;
+ break;
+ case SY:
+ door->_destY = _value._wordVal;
+ break;
+ case XX:
+ door->_x = _value._wordVal;
+ break;
+ case YY:
+ door->_y = _value._byteVal;
+ break;
+ case XL:
+ door->_width = _value._wordVal;
+ break;
+ case YL:
+ door->_height = _value._byteVal;
+ break;
+ case WX:
+ door->_walkToX = _value._wordVal;
+ break;
+ case WY:
+ door->_walkToY = _value._byteVal;
+ break;
+ case SP:
+ door->_SP = _value._byteVal;
+ break;
+ default:
+ warning("Object does not support changing this register.");
+ break;
+ }
+
+ return Finished;
+}
+
+Command::ExecuteResult ChangeObjectCommand::execute(GameData &gameData) {
+ Scene *const scene = gameData.getScene(_sceneId);
+ if (!scene) {
+ return Finished;
+ }
+
+ Object *const object = scene->getObject(_entityId);
+ if (!object) {
+ return Finished;
+ }
+
+ switch (_register) {
+ case AC:
+ object->_AC = _value._byteVal;
+ break;
+ case FA:
+ object->_FA = _value._byteVal;
+ break;
+ case FR:
+ object->_FR = _value._byteVal;
+ break;
+ case NA:
+ object->_NA = _value._byteVal;
+ break;
+ case FS:
+ object->_FS = _value._byteVal;
+ break;
+ case CA:
+ object->_CA = _value._byteVal;
+ break;
+ case XX:
+ object->_x = _value._wordVal;
+ break;
+ case YY:
+ object->_y = _value._byteVal;
+ break;
+ case XL:
+ object->_XL = _value._wordVal;
+ break;
+ case YL:
+ object->_YL = _value._byteVal;
+ break;
+ case WX:
+ object->_WX = _value._wordVal;
+ break;
+ case WY:
+ object->_WY = _value._byteVal;
+ break;
+ case SP:
+ object->_SP = _value._byteVal;
+ break;
+ default:
+ warning("Object does not support changing this register.");
+ break;
+ }
+
+ return Finished;
+}
+
+Command::ExecuteResult ChangeStaticCommand::execute(GameData &gameData) {
+ Scene *const scene = gameData.getScene(_sceneId);
+ if (!scene) {
+ return Finished;
+ }
+
+ Static *const stat = scene->getStatic(_entityId);
+ if (!stat) {
+ return Finished;
+ }
+
+ switch (_register) {
+ case AC:
+ stat->_active = _value._byteVal;
+ break;
+ case NM:
+ strncpy(stat->_name, _value._strVal, MAX_STR_LENGTH);
+ break;
+ case XX:
+ stat->_x = _value._wordVal;
+ break;
+ case YY:
+ stat->_y = _value._byteVal;
+ break;
+ case XL:
+ stat->_width = _value._wordVal;
+ break;
+ case YL:
+ stat->_height = _value._byteVal;
+ break;
+ case WX:
+ stat->_walkToX = _value._wordVal;
+ break;
+ case WY:
+ stat->_walkToY = _value._byteVal;
+ break;
+ case SP:
+ stat->_SP = _value._byteVal;
+ break;
+ default:
+ warning("Object does not support changing this register.");
+ break;
+ }
+
+ return Finished;
+}
+}
diff --git a/engines/mutationofjb/commands/changecommand.h b/engines/mutationofjb/commands/changecommand.h
new file mode 100644
index 0000000000..5b9a91e47e
--- /dev/null
+++ b/engines/mutationofjb/commands/changecommand.h
@@ -0,0 +1,120 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "mutationofjb/commands/seqcommand.h"
+#include "mutationofjb/game.h"
+
+namespace MutationOfJB {
+
+union ChangeCommandValue {
+ uint8 _byteVal;
+ uint16 _wordVal;
+ char _strVal[MAX_STR_LENGTH + 1];
+};
+
+class ChangeCommand : public SeqCommand {
+public:
+ enum ChangeRegister {
+ NM, // Name
+ LT, // Destination scene ID
+ SX, // Destination X
+ SY, // Destination Y
+ XX, // X
+ YY, // Y
+ XL, // Width
+ YL, // Height
+ WX, // Walk to X
+ WY, // Walk to Y
+ SP, //
+ AC, // Active
+ FA, // First animation
+ FR,
+ NA,
+ FS,
+ CA
+ };
+
+ enum ChangeOperation {
+ SetValue,
+ AddValue,
+ SubtractValue
+ };
+
+ ChangeCommand(uint8 sceneId, uint8 entityId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue& val) :
+ _sceneId(sceneId), _entityId(entityId), _register(reg), _operation(op), _value(val)
+ {}
+protected:
+ uint8 _sceneId;
+ uint8 _entityId;
+ ChangeRegister _register;
+ ChangeOperation _operation;
+ ChangeCommandValue _value;
+};
+
+class ChangeCommandParser : public SeqCommandParser {
+protected:
+ bool parseValueString(const Common::String &valueString, uint8 &sceneId, uint8 &entityId, ChangeCommand::ChangeRegister &reg, ChangeCommand::ChangeOperation &op, ChangeCommandValue &ccv);
+ int parseInteger(const char *val, ChangeCommand::ChangeOperation &op);
+};
+
+class ChangeObjectCommandParser : public ChangeCommandParser {
+public:
+ virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
+};
+
+class ChangeDoorCommandParser : public ChangeCommandParser {
+public:
+ virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
+};
+
+class ChangeStaticCommandParser : public ChangeCommandParser {
+public:
+ virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) override;
+};
+
+
+
+class ChangeDoorCommand : public ChangeCommand {
+public:
+ ChangeDoorCommand(uint8 sceneId, uint8 doorId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue& val)
+ : ChangeCommand(sceneId, doorId, reg, op, val)
+ {}
+ virtual ExecuteResult execute(GameData &gameData) override;
+};
+
+class ChangeObjectCommand : public ChangeCommand {
+public:
+ ChangeObjectCommand(uint8 sceneId, uint8 objectId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue& val)
+ : ChangeCommand(sceneId, objectId, reg, op, val)
+ {}
+ virtual ExecuteResult execute(GameData &gameData) override;
+};
+
+class ChangeStaticCommand : public ChangeCommand {
+public:
+ ChangeStaticCommand(uint8 sceneId, uint8 staticId, ChangeRegister reg, ChangeOperation op, const ChangeCommandValue& val)
+ : ChangeCommand(sceneId, staticId, reg, op, val)
+ {}
+ virtual ExecuteResult execute(GameData &gameData) override;
+};
+
+}
diff --git a/engines/mutationofjb/commands/command.h b/engines/mutationofjb/commands/command.h
index ab0ebc6da8..f8c160e3cb 100644
--- a/engines/mutationofjb/commands/command.h
+++ b/engines/mutationofjb/commands/command.h
@@ -36,8 +36,6 @@ class CallMacroCommand;
class ScriptParseContext;
class Command;
-typedef bool (*CommandParseFunc)(const Common::String &line, ScriptParseContext &parseContext, Command *&command);
-
class CommandParser {
public:
virtual ~CommandParser();
diff --git a/engines/mutationofjb/commands/ifcommand.cpp b/engines/mutationofjb/commands/ifcommand.cpp
index 5ba35bc3ea..8026c841e1 100644
--- a/engines/mutationofjb/commands/ifcommand.cpp
+++ b/engines/mutationofjb/commands/ifcommand.cpp
@@ -40,7 +40,7 @@ bool IfCommandParser::parse(const Common::String &line, ScriptParseContext &pars
return false;
}
- if (strncmp(line.c_str(), "IF", 2) != 0) {
+ if (!line.hasPrefix("IF")) {
return false;
}
diff --git a/engines/mutationofjb/commands/seqcommand.h b/engines/mutationofjb/commands/seqcommand.h
index 1d21f66948..90e302836e 100644
--- a/engines/mutationofjb/commands/seqcommand.h
+++ b/engines/mutationofjb/commands/seqcommand.h
@@ -30,6 +30,7 @@ namespace MutationOfJB {
class SeqCommandParser : public CommandParser
{
+public:
virtual void transition(ScriptParseContext &parseCtx, Command *oldCommand, Command *newCommand) override;
};
diff --git a/engines/mutationofjb/game.cpp b/engines/mutationofjb/game.cpp
index 740fb1cab6..9f517d6608 100644
--- a/engines/mutationofjb/game.cpp
+++ b/engines/mutationofjb/game.cpp
@@ -143,6 +143,15 @@ bool Scene::loadFromStream(Common::ReadStream &stream) {
return true;
}
+Door *Scene::getDoor(uint8 doorId) {
+ if (doorId == 0 || doorId > _noDoors) {
+ warning(_("Door %d does not exist"), doorId);
+ return nullptr;
+ }
+
+ return &_doors[doorId - 1];
+}
+
Object *Scene::getObject(uint8 objectId) {
if (objectId == 0 || objectId > _noObjects) {
warning(_("Object %d does not exist"), objectId);
@@ -152,6 +161,15 @@ Object *Scene::getObject(uint8 objectId) {
return &_objects[objectId - 1];
}
+Static *Scene::getStatic(uint8 staticId) {
+ if (staticId == 0 || staticId > _noStatics) {
+ warning(_("Static %d does not exist"), staticId);
+ return nullptr;
+ }
+
+ return &_statics[staticId - 1];
+}
+
GameData::GameData() : _currentScene(0) {}
Scene *GameData::getScene(uint8 sceneId)
diff --git a/engines/mutationofjb/game.h b/engines/mutationofjb/game.h
index d49a966001..eda178bf8f 100644
--- a/engines/mutationofjb/game.h
+++ b/engines/mutationofjb/game.h
@@ -93,7 +93,9 @@ struct Bitmap {
struct Scene {
+ Door *getDoor(uint8 objectId);
Object *getObject(uint8 objectId);
+ Static *getStatic(uint8 staticId);
uint8 _startup;
uint8 _unknown001;
diff --git a/engines/mutationofjb/module.mk b/engines/mutationofjb/module.mk
index 132d8698aa..16a0c3b06f 100644
--- a/engines/mutationofjb/module.mk
+++ b/engines/mutationofjb/module.mk
@@ -1,6 +1,7 @@
MODULE := engines/mutationofjb
MODULE_OBJS := \
+ commands/changecommand.o \
commands/command.o \
commands/conditionalcommand.o \
commands/endblockcommand.o \
diff --git a/engines/mutationofjb/script.cpp b/engines/mutationofjb/script.cpp
index a20c11eef0..0deeccbb73 100644
--- a/engines/mutationofjb/script.cpp
+++ b/engines/mutationofjb/script.cpp
@@ -29,6 +29,7 @@
#include "mutationofjb/commands/command.h"
#include "mutationofjb/commands/ifcommand.h"
#include "mutationofjb/commands/endblockcommand.h"
+#include "mutationofjb/commands/changecommand.h"
namespace MutationOfJB {
@@ -36,6 +37,9 @@ static CommandParser** getParsers() {
static CommandParser* parsers[] = {
new IfCommandParser,
new EndBlockCommandParser,
+ new ChangeDoorCommandParser,
+ new ChangeObjectCommandParser,
+ new ChangeStaticCommandParser,
nullptr
};
@@ -101,6 +105,7 @@ bool Script::loadFromStream(Common::SeekableReadStream &stream) {
_allCommands.push_back(currentCmd);
}
+ lastCmd = currentCmd;
lastParser = currentParser;
}