[Scummvm-git-logs] scummvm master -> 453d85b33dfddb6b49cbd58fae3e6926abf5703b

elasota noreply at scummvm.org
Thu Sep 5 00:04:55 UTC 2024


This automated email contains information about 9 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
91a9cf10fe MTROPOLIS: add stubs for numerous third-party modifiers
1ae5882baf MTROPOLIS: add listings and descriptions of known modifiers
7656dbab44 MTROPOLIS: fixes to include guards
31ff64b276 MTROPOLIS: add stubs for RWC plugin
86d3684728 MTROPOLIS: fix mapping of plugin enum to functions
b6cf098daa JANITORIAL: corrections to comments
0fa1add800 MTROPOLIS: Use correct name in name string of ThighBlaster modifier
f610969edb JANITORIAL: use tabs for indentation
453d85b33d JANITORIAL: remove redundant commented out code


Commit: 91a9cf10fe440bdb388cd3f99c0a9532de9bd972
    https://github.com/scummvm/scummvm/commit/91a9cf10fe440bdb388cd3f99c0a9532de9bd972
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
MTROPOLIS: add stubs for numerous third-party modifiers

Changed paths:
  A engines/mtropolis/plugin/axlogic.cpp
  A engines/mtropolis/plugin/axlogic.h
  A engines/mtropolis/plugin/axlogic_data.cpp
  A engines/mtropolis/plugin/axlogic_data.h
  A engines/mtropolis/plugin/ftts.cpp
  A engines/mtropolis/plugin/ftts.h
  A engines/mtropolis/plugin/ftts_data.cpp
  A engines/mtropolis/plugin/ftts_data.h
  A engines/mtropolis/plugin/hoologic.cpp
  A engines/mtropolis/plugin/hoologic.h
  A engines/mtropolis/plugin/hoologic_data.cpp
  A engines/mtropolis/plugin/hoologic_data.h
  A engines/mtropolis/plugin/kw.cpp
  A engines/mtropolis/plugin/kw.h
  A engines/mtropolis/plugin/kw_data.cpp
  A engines/mtropolis/plugin/kw_data.h
  A engines/mtropolis/plugin/mline.cpp
  A engines/mtropolis/plugin/mline.h
  A engines/mtropolis/plugin/mline_data.cpp
  A engines/mtropolis/plugin/mline_data.h
  A engines/mtropolis/plugin/thereware.cpp
  A engines/mtropolis/plugin/thereware.h
  A engines/mtropolis/plugin/thereware_data.cpp
  A engines/mtropolis/plugin/thereware_data.h
    engines/mtropolis/boot.cpp
    engines/mtropolis/data.cpp
    engines/mtropolis/data.h
    engines/mtropolis/module.mk
    engines/mtropolis/plugins.h


diff --git a/engines/mtropolis/boot.cpp b/engines/mtropolis/boot.cpp
index 1f7e9c152d9..3c06690b496 100644
--- a/engines/mtropolis/boot.cpp
+++ b/engines/mtropolis/boot.cpp
@@ -1078,6 +1078,12 @@ public:
 		kPlugInStandard,
 		kPlugInObsidian,
 		kPlugInMIDI,
+		kPlugInFTTS,
+		kPlugInKnowWonder,
+		kPlugInAxLogic,
+		kPlugInHoologic,
+		kPlugInMLine,
+		kPlugInThereware,
 	};
 
 	enum BitDepth {
@@ -1465,7 +1471,13 @@ void BootScriptContext::executeFunction(const Common::String &functionName, cons
 	const EnumBinding plugInEnum[] = {ENUM_BINDING(kPlugInMTI),
 									  ENUM_BINDING(kPlugInStandard),
 									  ENUM_BINDING(kPlugInObsidian),
-									  ENUM_BINDING(kPlugInMIDI)};
+									  ENUM_BINDING(kPlugInMIDI),
+									  ENUM_BINDING(kPlugInFTTS),
+									  ENUM_BINDING(kPlugInKnowWonder),
+									  ENUM_BINDING(kPlugInAxLogic),
+									  ENUM_BINDING(kPlugInHoologic),
+									  ENUM_BINDING(kPlugInMLine),
+									  ENUM_BINDING(kPlugInThereware),};
 
 	const EnumBinding bitDepthEnum[] = {ENUM_BINDING(kBitDepthAuto),
 										ENUM_BINDING(kBitDepth8),
@@ -2107,6 +2119,36 @@ Common::SharedPtr<MTropolis::PlugIn> loadMTIPlugIn(const MTropolisGameDescriptio
 	return mtiPlugIn;
 }
 
+Common::SharedPtr<MTropolis::PlugIn> loadFTTSPlugIn(const MTropolisGameDescription &gameDesc) {
+	Common::SharedPtr<MTropolis::PlugIn> fttsPlugIn(PlugIns::createFTTS());
+	return fttsPlugIn;
+}
+
+Common::SharedPtr<MTropolis::PlugIn> loadKnowWonderPlugIn(const MTropolisGameDescription &gameDesc) {
+	Common::SharedPtr<MTropolis::PlugIn> kwPlugIn(PlugIns::createKnowWonder());
+	return kwPlugIn;
+}
+
+Common::SharedPtr<MTropolis::PlugIn> loadAXLogicPlugIn(const MTropolisGameDescription &gameDesc) {
+	Common::SharedPtr<MTropolis::PlugIn> axPlugIn(PlugIns::createAXLogic());
+	return axPlugIn;
+}
+
+Common::SharedPtr<MTropolis::PlugIn> loadHoologicPlugIn(const MTropolisGameDescription &gameDesc) {
+	Common::SharedPtr<MTropolis::PlugIn> hlPlugIn(PlugIns::createHoologic());
+	return hlPlugIn;
+}
+
+Common::SharedPtr<MTropolis::PlugIn> loadMLinePlugIn(const MTropolisGameDescription &gameDesc) {
+	Common::SharedPtr<MTropolis::PlugIn> mlinePlugIn(PlugIns::createMLine());
+	return mlinePlugIn;
+}
+
+Common::SharedPtr<MTropolis::PlugIn> loadTherewarePlugIn(const MTropolisGameDescription &gameDesc) {
+	Common::SharedPtr<MTropolis::PlugIn> twPlugIn(PlugIns::createThereware());
+	return twPlugIn;
+}
+
 enum PlayerType {
 	kPlayerTypeNone,
 
@@ -2980,6 +3022,24 @@ BootConfiguration bootProject(const MTropolisGameDescription &gameDesc) {
 		case Boot::BootScriptContext::kPlugInMTI:
 			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
 			break;
+		case Boot::BootScriptContext::kPlugInFTTS:
+			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			break;
+		case Boot::BootScriptContext::kPlugInKnowWonder:
+			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			break;
+		case Boot::BootScriptContext::kPlugInAxLogic:
+			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			break;
+		case Boot::BootScriptContext::kPlugInHoologic:
+			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			break;
+		case Boot::BootScriptContext::kPlugInMLine:
+			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			break;
+		case Boot::BootScriptContext::kPlugInThereware:
+			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			break;
 		default:
 			error("Unknown plug-in ID");
 		}
diff --git a/engines/mtropolis/data.cpp b/engines/mtropolis/data.cpp
index 338ee8450af..c681c7edc48 100644
--- a/engines/mtropolis/data.cpp
+++ b/engines/mtropolis/data.cpp
@@ -416,6 +416,10 @@ bool Label::load(DataReader &reader) {
 	return reader.readU32(superGroupID) && reader.readU32(labelID);
 }
 
+bool UniversalTime::load(DataReader &reader) {
+	return reader.readS32(value) && reader.readS32(scale) && reader.readS32(base);
+}
+
 InternalTypeTaggedValue::InternalTypeTaggedValue() : type(0) {
 }
 
@@ -526,6 +530,11 @@ bool PlugInTypeTaggedValue::load(DataReader &reader) {
 		if (!reader.readS32(value.asInt))
 			return false;
 		break;
+	case kUniversalTime:
+		value.constructField(&ValueUnion::asUniversalTime);
+		if (!value.asUniversalTime.load(reader))
+			return false;
+		break;
 	case kIntegerRange:
 		value.constructField(&ValueUnion::asIntRange);
 		if (!value.asIntRange.load(reader))
@@ -563,6 +572,11 @@ bool PlugInTypeTaggedValue::load(DataReader &reader) {
 			if (!reader.readTerminatedStr(value.asString, length2))
 				return false;
 		} break;
+	case kRGBColor:
+		value.constructField(&ValueUnion::asColor);
+		if (!value.asColor.load(reader))
+			return false;
+		break;
 	case kVariableReference: {
 			value.constructField(&ValueUnion::asVarRefGUID);
 			uint32 extraDataSize;
diff --git a/engines/mtropolis/data.h b/engines/mtropolis/data.h
index bde42236e55..d08b650545e 100644
--- a/engines/mtropolis/data.h
+++ b/engines/mtropolis/data.h
@@ -403,6 +403,15 @@ struct Label {
 	uint32 labelID;
 };
 
+struct UniversalTime {
+	bool load(DataReader &reader);
+
+	int32 value;
+	int32 scale;
+	int32 base;
+};
+
+
 // mTropolis uses two separate type-tagged value formats.
 //
 // InternalTypeTaggedValue is used by internal modifiers for messenger payloads and set modifiers
@@ -459,6 +468,7 @@ struct PlugInTypeTaggedValue : public Common::NonCopyable {
 	enum TypeCode {
 		kNull = 0x00,
 		kInteger = 0x01,
+		kUniversalTime = 0x09,
 		kPoint = 0xa,
 		kIntegerRange = 0xb,
 		kFloat = 0xf,
@@ -466,6 +476,7 @@ struct PlugInTypeTaggedValue : public Common::NonCopyable {
 		kEvent = 0x17,
 		kLabel = 0x64,
 		kString = 0x66,
+		kRGBColor = 0x6c,
 		kIncomingData = 0x6e,
 		kVariableReference = 0x73,	// Has extra data
 	};
@@ -476,6 +487,8 @@ struct PlugInTypeTaggedValue : public Common::NonCopyable {
 
 		int32 asInt;
 		Point asPoint;
+		UniversalTime asUniversalTime;
+		ColorRGB16 asColor;
 		IntRange asIntRange;
 		XPFloatPOD asFloat;
 		uint16 asBoolean;
diff --git a/engines/mtropolis/module.mk b/engines/mtropolis/module.mk
index 474401e20bc..d6e5d749b04 100644
--- a/engines/mtropolis/module.mk
+++ b/engines/mtropolis/module.mk
@@ -19,14 +19,26 @@ MODULE_OBJS = \
 	modifiers.o \
 	modifier_factory.o \
 	mtropolis.o \
+	plugin/axlogic.o \
+	plugin/axlogic_data.o \
+	plugin/ftts.o \
+	plugin/ftts_data.o \
+	plugin/hoologic.o \
+	plugin/hoologic_data.o \
+	plugin/kw.o \
+	plugin/kw_data.o \
 	plugin/midi.o \
 	plugin/midi_data.o \
+	plugin/mline.o \
+	plugin/mline_data.o \
 	plugin/mti.o \
 	plugin/mti_data.o \
 	plugin/obsidian.o \
 	plugin/obsidian_data.o \
 	plugin/standard.o \
 	plugin/standard_data.o \
+	plugin/thereware.o \
+	plugin/thereware_data.o \
 	render.o \
 	runtime.o \
 	saveload.o \
diff --git a/engines/mtropolis/plugin/axlogic.cpp b/engines/mtropolis/plugin/axlogic.cpp
new file mode 100644
index 00000000000..b516dd3d263
--- /dev/null
+++ b/engines/mtropolis/plugin/axlogic.cpp
@@ -0,0 +1,85 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/axlogic.h"
+#include "mtropolis/plugins.h"
+
+namespace MTropolis {
+
+namespace AXLogic {
+
+AlienWriterModifier::AlienWriterModifier() {
+}
+
+AlienWriterModifier::~AlienWriterModifier() {
+}
+
+bool AlienWriterModifier::load(const PlugInModifierLoaderContext &context, const Data::AXLogic::AlienWriterModifier &data) {
+	return true;
+}
+
+bool AlienWriterModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState AlienWriterModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void AlienWriterModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void AlienWriterModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> AlienWriterModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new AlienWriterModifier(*this));
+}
+
+const char *AlienWriterModifier::getDefaultName() const {
+	return "AlienWriter Modifier"; // ???
+}
+
+AXLogicPlugIn::AXLogicPlugIn()
+	: _alienWriterModifierFactory(this) {
+}
+
+AXLogicPlugIn::~AXLogicPlugIn() {
+}
+
+void AXLogicPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
+	registrar->registerPlugInModifier("AlienWriter", &_alienWriterModifierFactory);
+}
+
+} // End of namespace AXLogic
+
+namespace PlugIns {
+
+Common::SharedPtr<PlugIn> createAXLogic() {
+	return Common::SharedPtr<PlugIn>(new AXLogic::AXLogicPlugIn());
+}
+
+} // End of namespace PlugIns
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/axlogic.h b/engines/mtropolis/plugin/axlogic.h
new file mode 100644
index 00000000000..52d8ab3f329
--- /dev/null
+++ b/engines/mtropolis/plugin/axlogic.h
@@ -0,0 +1,71 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_AXLOGIC_H
+#define MTROPOLIS_PLUGIN_AXLOGIC_H
+
+#include "mtropolis/modifiers.h"
+#include "mtropolis/modifier_factory.h"
+#include "mtropolis/runtime.h"
+#include "mtropolis/plugin/axlogic_data.h"
+
+namespace MTropolis {
+
+namespace AXLogic {
+
+class AlienWriterModifier : public Modifier {
+public:
+	AlienWriterModifier();
+	~AlienWriterModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::AXLogic::AlienWriterModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "AlienWriter Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class AXLogicPlugIn : public MTropolis::PlugIn {
+public:
+	AXLogicPlugIn();
+	~AXLogicPlugIn();
+
+	void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
+
+private:
+	PlugInModifierFactory<AlienWriterModifier, Data::AXLogic::AlienWriterModifier> _alienWriterModifierFactory;
+};
+
+} // End of namespace AXLogic
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/axlogic_data.cpp b/engines/mtropolis/plugin/axlogic_data.cpp
new file mode 100644
index 00000000000..cb521d2a191
--- /dev/null
+++ b/engines/mtropolis/plugin/axlogic_data.cpp
@@ -0,0 +1,43 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/axlogic_data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace AXLogic {
+
+DataReadErrorCode AlienWriterModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 1)
+		return kDataReadErrorUnsupportedRevision;
+
+    error("Data structure loading for the AlienWriter modifier is not implemented.");
+
+	return kDataReadErrorNone;
+}
+
+} // End of namespace AXLogic
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/axlogic_data.h b/engines/mtropolis/plugin/axlogic_data.h
new file mode 100644
index 00000000000..4cf1d542ae0
--- /dev/null
+++ b/engines/mtropolis/plugin/axlogic_data.h
@@ -0,0 +1,44 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_AXLOGIC_DATA_H
+#define MTROPOLIS_PLUGIN_AXLOGIC_DATA_H
+
+#include "mtropolis/data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace AXLogic {
+
+struct AlienWriterModifier : public PlugInModifierData {
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+} // End of namespace AXLogic
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/ftts.cpp b/engines/mtropolis/plugin/ftts.cpp
new file mode 100644
index 00000000000..8b239e37248
--- /dev/null
+++ b/engines/mtropolis/plugin/ftts.cpp
@@ -0,0 +1,122 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/ftts.h"
+#include "mtropolis/plugins.h"
+
+namespace MTropolis {
+
+namespace FTTS {
+
+MotionModifier::MotionModifier() {
+}
+
+MotionModifier::~MotionModifier() {
+}
+
+bool MotionModifier::load(const PlugInModifierLoaderContext &context, const Data::FTTS::MotionModifier &data) {
+	return true;
+}
+
+bool MotionModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState MotionModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void MotionModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void MotionModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> MotionModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new MotionModifier(*this));
+}
+
+const char *MotionModifier::getDefaultName() const {
+	return "Motion Modifier"; // ???
+}
+
+SparkleModifier::SparkleModifier() {
+}
+
+SparkleModifier::~SparkleModifier() {
+}
+
+bool SparkleModifier::load(const PlugInModifierLoaderContext &context, const Data::FTTS::SparkleModifier &data) {
+	return true;
+}
+
+bool SparkleModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState SparkleModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void SparkleModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void SparkleModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> SparkleModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new SparkleModifier(*this));
+}
+
+const char *SparkleModifier::getDefaultName() const {
+	return "Sparkle Modifier"; // ???
+}
+
+FTTSPlugIn::FTTSPlugIn()
+	: _motionModifierFactory(this)
+	, _sparkleModifierFactory(this) {
+}
+
+FTTSPlugIn::~FTTSPlugIn() {
+}
+
+void FTTSPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
+	registrar->registerPlugInModifier("Motion", &_motionModifierFactory);
+	registrar->registerPlugInModifier("Sparkle", &_sparkleModifierFactory);
+}
+
+} // End of namespace FTTS
+
+namespace PlugIns {
+
+Common::SharedPtr<PlugIn> createFTTS() {
+	return Common::SharedPtr<PlugIn>(new FTTS::FTTSPlugIn());
+}
+
+} // End of namespace PlugIns
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/ftts.h b/engines/mtropolis/plugin/ftts.h
new file mode 100644
index 00000000000..f255a9d3e17
--- /dev/null
+++ b/engines/mtropolis/plugin/ftts.h
@@ -0,0 +1,94 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_FTTS_H
+#define MTROPOLIS_PLUGIN_FTTS_H
+
+#include "mtropolis/modifiers.h"
+#include "mtropolis/modifier_factory.h"
+#include "mtropolis/runtime.h"
+#include "mtropolis/plugin/ftts_data.h"
+
+namespace MTropolis {
+
+namespace FTTS {
+
+class MotionModifier : public Modifier {
+public:
+	MotionModifier();
+	~MotionModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::FTTS::MotionModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "Motion Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class SparkleModifier : public Modifier {
+public:
+	SparkleModifier();
+	~SparkleModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::FTTS::SparkleModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "Sparkle Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class FTTSPlugIn : public MTropolis::PlugIn {
+public:
+	FTTSPlugIn();
+	~FTTSPlugIn();
+
+	void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
+
+private:
+	PlugInModifierFactory<MotionModifier, Data::FTTS::MotionModifier> _motionModifierFactory;
+	PlugInModifierFactory<SparkleModifier, Data::FTTS::SparkleModifier> _sparkleModifierFactory;
+};
+
+} // End of namespace FTTS
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/ftts_data.cpp b/engines/mtropolis/plugin/ftts_data.cpp
new file mode 100644
index 00000000000..899c4c55d8f
--- /dev/null
+++ b/engines/mtropolis/plugin/ftts_data.cpp
@@ -0,0 +1,63 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/ftts_data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace FTTS {
+
+DataReadErrorCode MotionModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Event.load(reader) || !unknown3Point.load(reader) || !unknown4Bool.load(reader) || !unknown5Point.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Int.load(reader) || !unknown7Float.load(reader) || !unknown8Int.load(reader) || !unknown9Event.load(reader) || !unknown10Label.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown11Null.load(reader) || !unknown12Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode SparkleModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Event.load(reader) || !unknown3Int.load(reader) || !unknown4Int.load(reader) || !unknown5Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Int.load(reader) || !unknown7Int.load(reader) || !unknown8Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+} // End of namespace FTTS
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/ftts_data.h b/engines/mtropolis/plugin/ftts_data.h
new file mode 100644
index 00000000000..81d75298c21
--- /dev/null
+++ b/engines/mtropolis/plugin/ftts_data.h
@@ -0,0 +1,69 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_FTTS_DATA_H
+#define MTROPOLIS_PLUGIN_FTTS_DATA_H
+
+#include "mtropolis/data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace FTTS {
+
+struct MotionModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Point;
+	PlugInTypeTaggedValue unknown4Bool;
+	PlugInTypeTaggedValue unknown5Point;
+	PlugInTypeTaggedValue unknown6Int;
+	PlugInTypeTaggedValue unknown7Float;
+	PlugInTypeTaggedValue unknown8Int;
+	PlugInTypeTaggedValue unknown9Event;
+	PlugInTypeTaggedValue unknown10Label;
+	PlugInTypeTaggedValue unknown11Null;
+	PlugInTypeTaggedValue unknown12Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct SparkleModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Int;
+	PlugInTypeTaggedValue unknown4Int;
+	PlugInTypeTaggedValue unknown5Int;
+	PlugInTypeTaggedValue unknown6Int;
+	PlugInTypeTaggedValue unknown7Int;
+	PlugInTypeTaggedValue unknown8Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+} // End of namespace FTTS
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/hoologic.cpp b/engines/mtropolis/plugin/hoologic.cpp
new file mode 100644
index 00000000000..9f07c1252b8
--- /dev/null
+++ b/engines/mtropolis/plugin/hoologic.cpp
@@ -0,0 +1,387 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/hoologic.h"
+#include "mtropolis/plugins.h"
+
+namespace MTropolis {
+
+namespace Hoologic {
+
+BitmapVariableModifier::BitmapVariableModifier() {
+}
+
+BitmapVariableModifier::~BitmapVariableModifier() {
+}
+
+bool BitmapVariableModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::BitmapVariableModifier &data) {
+	return true;
+}
+
+bool BitmapVariableModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState BitmapVariableModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void BitmapVariableModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void BitmapVariableModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> BitmapVariableModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new BitmapVariableModifier(*this));
+}
+
+const char *BitmapVariableModifier::getDefaultName() const {
+	return "Bitmap Variable Modifier"; // ???
+}
+
+CaptureBitmapModifier::CaptureBitmapModifier() {
+}
+
+CaptureBitmapModifier::~CaptureBitmapModifier() {
+}
+
+bool CaptureBitmapModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::CaptureBitmapModifier &data) {
+	return true;
+}
+
+bool CaptureBitmapModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState CaptureBitmapModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void CaptureBitmapModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void CaptureBitmapModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> CaptureBitmapModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new CaptureBitmapModifier(*this));
+}
+
+const char *CaptureBitmapModifier::getDefaultName() const {
+	return "Capture Bitmap Modifier"; // ???
+}
+
+ImportBitmapModifier::ImportBitmapModifier() {
+}
+
+ImportBitmapModifier::~ImportBitmapModifier() {
+}
+
+bool ImportBitmapModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::ImportBitmapModifier &data) {
+	return true;
+}
+
+bool ImportBitmapModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState ImportBitmapModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void ImportBitmapModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void ImportBitmapModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> ImportBitmapModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new ImportBitmapModifier(*this));
+}
+
+const char *ImportBitmapModifier::getDefaultName() const {
+	return "Import Bitmap Modifier"; // ???
+}
+
+DisplayBitmapModifier::DisplayBitmapModifier() {
+}
+
+DisplayBitmapModifier::~DisplayBitmapModifier() {
+}
+
+bool DisplayBitmapModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::DisplayBitmapModifier &data) {
+	return true;
+}
+
+bool DisplayBitmapModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState DisplayBitmapModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void DisplayBitmapModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void DisplayBitmapModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> DisplayBitmapModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new DisplayBitmapModifier(*this));
+}
+
+const char *DisplayBitmapModifier::getDefaultName() const {
+	return "Display Bitmap Modifier"; // ???
+}
+
+ScaleBitmapModifier::ScaleBitmapModifier() {
+}
+
+ScaleBitmapModifier::~ScaleBitmapModifier() {
+}
+
+bool ScaleBitmapModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::ScaleBitmapModifier &data) {
+	return true;
+}
+
+bool ScaleBitmapModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState ScaleBitmapModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void ScaleBitmapModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void ScaleBitmapModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> ScaleBitmapModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new ScaleBitmapModifier(*this));
+}
+
+const char *ScaleBitmapModifier::getDefaultName() const {
+	return "Scale Bitmap Modifier"; // ???
+}
+
+SaveBitmapModifier::SaveBitmapModifier() {
+}
+
+SaveBitmapModifier::~SaveBitmapModifier() {
+}
+
+bool SaveBitmapModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::SaveBitmapModifier &data) {
+	return true;
+}
+
+bool SaveBitmapModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState SaveBitmapModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void SaveBitmapModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void SaveBitmapModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> SaveBitmapModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new SaveBitmapModifier(*this));
+}
+
+const char *SaveBitmapModifier::getDefaultName() const {
+	return "Save Bitmap Modifier"; // ???
+}
+
+PrintBitmapModifier::PrintBitmapModifier() {
+}
+
+PrintBitmapModifier::~PrintBitmapModifier() {
+}
+
+bool PrintBitmapModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::PrintBitmapModifier &data) {
+	return true;
+}
+
+bool PrintBitmapModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState PrintBitmapModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void PrintBitmapModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void PrintBitmapModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> PrintBitmapModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new PrintBitmapModifier(*this));
+}
+
+const char *PrintBitmapModifier::getDefaultName() const {
+	return "Print Bitmap Modifier"; // ???
+}
+
+PainterModifier::PainterModifier() {
+}
+
+PainterModifier::~PainterModifier() {
+}
+
+bool PainterModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::PainterModifier &data) {
+	return true;
+}
+
+bool PainterModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState PainterModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void PainterModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void PainterModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> PainterModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new PainterModifier(*this));
+}
+
+const char *PainterModifier::getDefaultName() const {
+	return "Painter Modifier"; // ???
+}
+
+KeyStateModifier::KeyStateModifier() {
+}
+
+KeyStateModifier::~KeyStateModifier() {
+}
+
+bool KeyStateModifier::load(const PlugInModifierLoaderContext &context, const Data::Hoologic::KeyStateModifier &data) {
+	return true;
+}
+
+bool KeyStateModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState KeyStateModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void KeyStateModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void KeyStateModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> KeyStateModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new KeyStateModifier(*this));
+}
+
+const char *KeyStateModifier::getDefaultName() const {
+	return "KeyState Modifier"; // ???
+}
+
+HoologicPlugIn::HoologicPlugIn()
+	: _bitmapVariableModifierFactory(this)
+	, _captureBitmapModifierFactory(this)
+	, _importBitmapModifierFactory(this)
+	, _displayBitmapModifierFactory(this)
+	, _scaleBitmapModifierFactory(this)
+	, _saveBitmapModifierFactory(this)
+	, _printBitmapModifierFactory(this)
+	, _painterModifierFactory(this)
+	, _keyStateModifierFactory(this)
+	{	
+}
+
+HoologicPlugIn::~HoologicPlugIn() {
+}
+
+void HoologicPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
+	//Bitmap plugin
+	registrar->registerPlugInModifier("hlBitmapVariable", &_bitmapVariableModifierFactory);
+	registrar->registerPlugInModifier("hlCaptureBitmap", &_captureBitmapModifierFactory);
+	registrar->registerPlugInModifier("hlImportBitmap", &_importBitmapModifierFactory);
+	registrar->registerPlugInModifier("hlDisplayBitmap", &_displayBitmapModifierFactory);
+	registrar->registerPlugInModifier("hlScaleBitmap", &_scaleBitmapModifierFactory);
+	registrar->registerPlugInModifier("hlSaveBitmap", &_saveBitmapModifierFactory);
+	registrar->registerPlugInModifier("hlPrintBitmap", &_printBitmapModifierFactory);
+
+	//Painter plugin
+	registrar->registerPlugInModifier("hlPainter", &_painterModifierFactory);
+
+	//KeyState plugin
+	registrar->registerPlugInModifier("hlKeyState", &_keyStateModifierFactory);
+}
+
+} // End of namespace Hoologic
+
+namespace PlugIns {
+
+Common::SharedPtr<PlugIn> createHoologic() {
+	return Common::SharedPtr<PlugIn>(new Hoologic::HoologicPlugIn());
+}
+
+} // End of namespace PlugIns
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/hoologic.h b/engines/mtropolis/plugin/hoologic.h
new file mode 100644
index 00000000000..82a6299cbae
--- /dev/null
+++ b/engines/mtropolis/plugin/hoologic.h
@@ -0,0 +1,257 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_HOOLOGIC_H
+#define MTROPOLIS_PLUGIN_HOOLOGIC_H
+
+#include "mtropolis/modifiers.h"
+#include "mtropolis/modifier_factory.h"
+#include "mtropolis/runtime.h"
+#include "mtropolis/plugin/hoologic_data.h"
+
+namespace MTropolis {
+
+namespace Hoologic {
+
+class BitmapVariableModifier : public Modifier {
+public:
+	BitmapVariableModifier();
+	~BitmapVariableModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::BitmapVariableModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "BitmapVariable Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class CaptureBitmapModifier : public Modifier {
+public:
+	CaptureBitmapModifier();
+	~CaptureBitmapModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::CaptureBitmapModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "CaptureBitmap Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class ImportBitmapModifier : public Modifier {
+public:
+	ImportBitmapModifier();
+	~ImportBitmapModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::ImportBitmapModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "ImportBitmap Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class DisplayBitmapModifier : public Modifier {
+public:
+	DisplayBitmapModifier();
+	~DisplayBitmapModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::DisplayBitmapModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "DisplayBitmap Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class ScaleBitmapModifier : public Modifier {
+public:
+	ScaleBitmapModifier();
+	~ScaleBitmapModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::ScaleBitmapModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "ScaleBitmap Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class SaveBitmapModifier : public Modifier {
+public:
+	SaveBitmapModifier();
+	~SaveBitmapModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::SaveBitmapModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "SaveBitmap Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class PrintBitmapModifier : public Modifier {
+public:
+	PrintBitmapModifier();
+	~PrintBitmapModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::PrintBitmapModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "PrintBitmap Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class PainterModifier : public Modifier {
+public:
+	PainterModifier();
+	~PainterModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::PainterModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "Painter Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class KeyStateModifier : public Modifier {
+public:
+	KeyStateModifier();
+	~KeyStateModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Hoologic::KeyStateModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+	// bool isVariable() const override { return true; }
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "KeyState Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class HoologicPlugIn : public MTropolis::PlugIn {
+public:
+	HoologicPlugIn();
+	~HoologicPlugIn();
+
+	void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
+
+private:
+	PlugInModifierFactory<BitmapVariableModifier, Data::Hoologic::BitmapVariableModifier> _bitmapVariableModifierFactory;
+	PlugInModifierFactory<CaptureBitmapModifier, Data::Hoologic::CaptureBitmapModifier> _captureBitmapModifierFactory;
+	PlugInModifierFactory<ImportBitmapModifier, Data::Hoologic::ImportBitmapModifier> _importBitmapModifierFactory;
+	PlugInModifierFactory<DisplayBitmapModifier, Data::Hoologic::DisplayBitmapModifier> _displayBitmapModifierFactory;
+	PlugInModifierFactory<ScaleBitmapModifier, Data::Hoologic::ScaleBitmapModifier> _scaleBitmapModifierFactory;
+	PlugInModifierFactory<SaveBitmapModifier, Data::Hoologic::SaveBitmapModifier> _saveBitmapModifierFactory;
+	PlugInModifierFactory<PrintBitmapModifier, Data::Hoologic::PrintBitmapModifier> _printBitmapModifierFactory;
+	PlugInModifierFactory<PainterModifier, Data::Hoologic::PainterModifier> _painterModifierFactory;
+	PlugInModifierFactory<KeyStateModifier, Data::Hoologic::KeyStateModifier> _keyStateModifierFactory;
+};
+
+} // End of namespace FTTS
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/hoologic_data.cpp b/engines/mtropolis/plugin/hoologic_data.cpp
new file mode 100644
index 00000000000..5fa2f7091d1
--- /dev/null
+++ b/engines/mtropolis/plugin/hoologic_data.cpp
@@ -0,0 +1,124 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/hoologic_data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace Hoologic {
+
+DataReadErrorCode BitmapVariableModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	//Seemingly no data to load
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode CaptureBitmapModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2VarRef.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode ImportBitmapModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Bool.load(reader) || !unknown3Bool.load(reader) || !unknown4VarRef.load(reader) || !unknown5VarRef.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode DisplayBitmapModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2VarRef.load(reader) || !unknown3VarRef.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode ScaleBitmapModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2VarRef.load(reader) || !unknown3IncomingData.load(reader) || !unknown4Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode SaveBitmapModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2VarRef.load(reader) || !unknown3Bool.load(reader) || !unknown4Bool.load(reader) || !unknown5VarRef.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode PrintBitmapModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2VarRef.load(reader) || !unknown3Bool.load(reader) || !unknown4Bool.load(reader) || !unknown5Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Int.load(reader) || !unknown7Null.load(reader) || !unknown8Null.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode PainterModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+    error("Data structure loading for the Painter modifier is not implemented.");
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode KeyStateModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	//Seemingly no data to load
+
+	return kDataReadErrorNone;
+}
+
+} // End of namespace Hoologic
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/hoologic_data.h b/engines/mtropolis/plugin/hoologic_data.h
new file mode 100644
index 00000000000..29a82d2e8cd
--- /dev/null
+++ b/engines/mtropolis/plugin/hoologic_data.h
@@ -0,0 +1,111 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_Hoologic_DATA_H
+#define MTROPOLIS_PLUGIN_Hoologic_DATA_H
+
+#include "mtropolis/data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace Hoologic {
+
+struct BitmapVariableModifier : public PlugInModifierData {
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct CaptureBitmapModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2VarRef;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct ImportBitmapModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Bool;
+	PlugInTypeTaggedValue unknown3Bool;
+	PlugInTypeTaggedValue unknown4VarRef;
+	PlugInTypeTaggedValue unknown5VarRef;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct DisplayBitmapModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2VarRef;
+	PlugInTypeTaggedValue unknown3VarRef;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct ScaleBitmapModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2VarRef;
+	PlugInTypeTaggedValue unknown3IncomingData;
+	PlugInTypeTaggedValue unknown4Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct SaveBitmapModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2VarRef;
+	PlugInTypeTaggedValue unknown3Bool;
+	PlugInTypeTaggedValue unknown4Bool;
+	PlugInTypeTaggedValue unknown5VarRef;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct PrintBitmapModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2VarRef;
+	PlugInTypeTaggedValue unknown3Bool;
+	PlugInTypeTaggedValue unknown4Bool;
+	PlugInTypeTaggedValue unknown5Int;
+	PlugInTypeTaggedValue unknown6Int;
+	PlugInTypeTaggedValue unknown7Null;
+	PlugInTypeTaggedValue unknown8Null;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct PainterModifier : public PlugInModifierData {
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct KeyStateModifier : public PlugInModifierData {
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+} // End of namespace Hoologic
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/kw.cpp b/engines/mtropolis/plugin/kw.cpp
new file mode 100644
index 00000000000..03a5af933de
--- /dev/null
+++ b/engines/mtropolis/plugin/kw.cpp
@@ -0,0 +1,85 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/kw.h"
+#include "mtropolis/plugins.h"
+
+namespace MTropolis {
+
+namespace KW {
+
+StrUtilModifier::StrUtilModifier() {
+}
+
+StrUtilModifier::~StrUtilModifier() {
+}
+
+bool StrUtilModifier::load(const PlugInModifierLoaderContext &context, const Data::KW::StrUtilModifier &data) {
+	return true;
+}
+
+bool StrUtilModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState StrUtilModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void StrUtilModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void StrUtilModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> StrUtilModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new StrUtilModifier(*this));
+}
+
+const char *StrUtilModifier::getDefaultName() const {
+	return "StrUtil Modifier"; // ???
+}
+
+KnowWonderPlugIn::KnowWonderPlugIn()
+	: _strUtilModifierFactory(this) {
+}
+
+KnowWonderPlugIn::~KnowWonderPlugIn() {
+}
+
+void KnowWonderPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
+	registrar->registerPlugInModifier("StrUtil", &_strUtilModifierFactory);
+}
+
+} // End of namespace KW
+
+namespace PlugIns {
+
+Common::SharedPtr<PlugIn> createKnowWonder() {
+	return Common::SharedPtr<PlugIn>(new KW::KnowWonderPlugIn());
+}
+
+} // End of namespace PlugIns
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/kw.h b/engines/mtropolis/plugin/kw.h
new file mode 100644
index 00000000000..9ba2a300b4f
--- /dev/null
+++ b/engines/mtropolis/plugin/kw.h
@@ -0,0 +1,71 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_KW_H
+#define MTROPOLIS_PLUGIN_KW_H
+
+#include "mtropolis/modifiers.h"
+#include "mtropolis/modifier_factory.h"
+#include "mtropolis/runtime.h"
+#include "mtropolis/plugin/kw_data.h"
+
+namespace MTropolis {
+
+namespace KW {
+
+class StrUtilModifier : public Modifier {
+public:
+	StrUtilModifier();
+	~StrUtilModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::KW::StrUtilModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "StrUtil Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class KnowWonderPlugIn : public MTropolis::PlugIn {
+public:
+	KnowWonderPlugIn();
+	~KnowWonderPlugIn();
+
+	void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
+
+private:
+	PlugInModifierFactory<StrUtilModifier, Data::KW::StrUtilModifier> _strUtilModifierFactory;
+};
+
+} // End of namespace KW
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/kw_data.cpp b/engines/mtropolis/plugin/kw_data.cpp
new file mode 100644
index 00000000000..4ac6a0e2a89
--- /dev/null
+++ b/engines/mtropolis/plugin/kw_data.cpp
@@ -0,0 +1,43 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/kw_data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace KW {
+
+DataReadErrorCode StrUtilModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	// Seemingly no data to load
+
+	return kDataReadErrorNone;
+}
+
+} // End of namespace KW
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/kw_data.h b/engines/mtropolis/plugin/kw_data.h
new file mode 100644
index 00000000000..c5ad100df18
--- /dev/null
+++ b/engines/mtropolis/plugin/kw_data.h
@@ -0,0 +1,44 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_KW_DATA_H
+#define MTROPOLIS_PLUGIN_KW_DATA_H
+
+#include "mtropolis/data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace KW {
+
+struct StrUtilModifier : public PlugInModifierData {
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+} // End of namespace KW
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/mline.cpp b/engines/mtropolis/plugin/mline.cpp
new file mode 100644
index 00000000000..4db9e2090b0
--- /dev/null
+++ b/engines/mtropolis/plugin/mline.cpp
@@ -0,0 +1,86 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/mline.h"
+#include "mtropolis/plugins.h"
+
+namespace MTropolis {
+
+namespace MLine {
+
+MLineLauncherModifier::MLineLauncherModifier() {
+}
+
+MLineLauncherModifier::~MLineLauncherModifier() {
+}
+
+bool MLineLauncherModifier::load(const PlugInModifierLoaderContext &context, const Data::MLine::MLineLauncherModifier &data) {
+	return true;
+}
+
+bool MLineLauncherModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState MLineLauncherModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void MLineLauncherModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void MLineLauncherModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> MLineLauncherModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new MLineLauncherModifier(*this));
+}
+
+const char *MLineLauncherModifier::getDefaultName() const {
+	return "mLine Launcher Modifier"; // ???
+}
+
+MLinePlugIn::MLinePlugIn()
+	: _mlineLauncherModifierFactory(this) {
+}
+
+MLinePlugIn::~MLinePlugIn() {
+}
+
+void MLinePlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
+	//URLaunch modifier by mLine
+	registrar->registerPlugInModifier("mLine_launcher", &_mlineLauncherModifierFactory);
+}
+
+} // End of namespace MLine
+
+namespace PlugIns {
+
+Common::SharedPtr<PlugIn> createMLine() {
+	return Common::SharedPtr<PlugIn>(new MLine::MLinePlugIn());
+}
+
+} // End of namespace PlugIns
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/mline.h b/engines/mtropolis/plugin/mline.h
new file mode 100644
index 00000000000..dd187712aa0
--- /dev/null
+++ b/engines/mtropolis/plugin/mline.h
@@ -0,0 +1,71 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_MLINE_H
+#define MTROPOLIS_PLUGIN_MLINE_H
+
+#include "mtropolis/modifiers.h"
+#include "mtropolis/modifier_factory.h"
+#include "mtropolis/runtime.h"
+#include "mtropolis/plugin/mline_data.h"
+
+namespace MTropolis {
+
+namespace MLine {
+
+class MLineLauncherModifier : public Modifier {
+public:
+	MLineLauncherModifier();
+	~MLineLauncherModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::MLine::MLineLauncherModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "mLine Launcher Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class MLinePlugIn : public MTropolis::PlugIn {
+public:
+	MLinePlugIn();
+	~MLinePlugIn();
+
+	void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
+
+private:
+	PlugInModifierFactory<MLineLauncherModifier, Data::MLine::MLineLauncherModifier> _mlineLauncherModifierFactory;
+};
+
+} // End of namespace MLine
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/mline_data.cpp b/engines/mtropolis/plugin/mline_data.cpp
new file mode 100644
index 00000000000..34fa69c8fc6
--- /dev/null
+++ b/engines/mtropolis/plugin/mline_data.cpp
@@ -0,0 +1,50 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/mline_data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace MLine {
+
+DataReadErrorCode MLineLauncherModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1String.load(reader) || !unknown2String.load(reader) || !unknown3String.load(reader) || !unknown4Int.load(reader) || !unknown5Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Bool.load(reader) || !unknown7Event.load(reader) || !unknown8Bool.load(reader) || !unknown9Bool.load(reader) || !unknown10Bool.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown11Bool.load(reader) || !unknown12Bool.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+} // End of namespace MLine
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/mline_data.h b/engines/mtropolis/plugin/mline_data.h
new file mode 100644
index 00000000000..18f6e5472c9
--- /dev/null
+++ b/engines/mtropolis/plugin/mline_data.h
@@ -0,0 +1,56 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_FTTS_DATA_H
+#define MTROPOLIS_PLUGIN_FTTS_DATA_H
+
+#include "mtropolis/data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace MLine {
+
+struct MLineLauncherModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1String;
+	PlugInTypeTaggedValue unknown2String;
+	PlugInTypeTaggedValue unknown3String;
+	PlugInTypeTaggedValue unknown4Int;
+	PlugInTypeTaggedValue unknown5Int;
+	PlugInTypeTaggedValue unknown6Bool;
+	PlugInTypeTaggedValue unknown7Event;
+	PlugInTypeTaggedValue unknown8Bool;
+	PlugInTypeTaggedValue unknown9Bool;
+	PlugInTypeTaggedValue unknown10Bool;
+	PlugInTypeTaggedValue unknown11Bool;
+	PlugInTypeTaggedValue unknown12Bool;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+} // End of namespace MLine
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/thereware.cpp b/engines/mtropolis/plugin/thereware.cpp
new file mode 100644
index 00000000000..8012c52b3b9
--- /dev/null
+++ b/engines/mtropolis/plugin/thereware.cpp
@@ -0,0 +1,466 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/thereware.h"
+#include "mtropolis/plugins.h"
+
+namespace MTropolis {
+
+namespace Thereware {
+
+RotatorModifier::RotatorModifier() {
+}
+
+RotatorModifier::~RotatorModifier() {
+}
+
+bool RotatorModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::RotatorModifier &data) {
+	return true;
+}
+
+bool RotatorModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState RotatorModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void RotatorModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void RotatorModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> RotatorModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new RotatorModifier(*this));
+}
+
+const char *RotatorModifier::getDefaultName() const {
+	return "Rotator Modifier"; // ???
+}
+
+TrackerModifier::TrackerModifier() {
+}
+
+TrackerModifier::~TrackerModifier() {
+}
+
+bool TrackerModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::TrackerModifier &data) {
+	return true;
+}
+
+bool TrackerModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState TrackerModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void TrackerModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void TrackerModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> TrackerModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new TrackerModifier(*this));
+}
+
+const char *TrackerModifier::getDefaultName() const {
+	return "Tracker Modifier"; // ???
+}
+
+DoubleClickModifier::DoubleClickModifier() {
+}
+
+DoubleClickModifier::~DoubleClickModifier() {
+}
+
+bool DoubleClickModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::DoubleClickModifier &data) {
+	return true;
+}
+
+bool DoubleClickModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState DoubleClickModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void DoubleClickModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void DoubleClickModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> DoubleClickModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new DoubleClickModifier(*this));
+}
+
+const char *DoubleClickModifier::getDefaultName() const {
+	return "DoubleClick Modifier"; // ???
+}
+
+MouseTrapModifier::MouseTrapModifier() {
+}
+
+MouseTrapModifier::~MouseTrapModifier() {
+}
+
+bool MouseTrapModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::MouseTrapModifier &data) {
+	return true;
+}
+
+bool MouseTrapModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState MouseTrapModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void MouseTrapModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void MouseTrapModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> MouseTrapModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new MouseTrapModifier(*this));
+}
+
+const char *MouseTrapModifier::getDefaultName() const {
+	return "MouseTrap Modifier"; // ???
+}
+
+WrapAroundModifier::WrapAroundModifier() {
+}
+
+WrapAroundModifier::~WrapAroundModifier() {
+}
+
+bool WrapAroundModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::WrapAroundModifier &data) {
+	return true;
+}
+
+bool WrapAroundModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState WrapAroundModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void WrapAroundModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void WrapAroundModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> WrapAroundModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new WrapAroundModifier(*this));
+}
+
+const char *WrapAroundModifier::getDefaultName() const {
+	return "WrapAround Modifier"; // ???
+}
+
+EasyScrollerModifier::EasyScrollerModifier() {
+}
+
+EasyScrollerModifier::~EasyScrollerModifier() {
+}
+
+bool EasyScrollerModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::EasyScrollerModifier &data) {
+	return true;
+}
+
+bool EasyScrollerModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState EasyScrollerModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void EasyScrollerModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void EasyScrollerModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> EasyScrollerModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new EasyScrollerModifier(*this));
+}
+
+const char *EasyScrollerModifier::getDefaultName() const {
+	return "EasyScroller Modifier"; // ???
+}
+
+GoThereModifier::GoThereModifier() {
+}
+
+GoThereModifier::~GoThereModifier() {
+}
+
+bool GoThereModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::GoThereModifier &data) {
+	return true;
+}
+
+bool GoThereModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState GoThereModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void GoThereModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void GoThereModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> GoThereModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new GoThereModifier(*this));
+}
+
+const char *GoThereModifier::getDefaultName() const {
+	return "GoThere Modifier"; // ???
+}
+
+RandomizerModifier::RandomizerModifier() {
+}
+
+RandomizerModifier::~RandomizerModifier() {
+}
+
+bool RandomizerModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::RandomizerModifier &data) {
+	return true;
+}
+
+bool RandomizerModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState RandomizerModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void RandomizerModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void RandomizerModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> RandomizerModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new RandomizerModifier(*this));
+}
+
+const char *RandomizerModifier::getDefaultName() const {
+	return "Randomizer Modifier"; // ???
+}
+
+TimeLoopModifier::TimeLoopModifier() {
+}
+
+TimeLoopModifier::~TimeLoopModifier() {
+}
+
+bool TimeLoopModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::TimeLoopModifier &data) {
+	return true;
+}
+
+bool TimeLoopModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState TimeLoopModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void TimeLoopModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void TimeLoopModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> TimeLoopModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new TimeLoopModifier(*this));
+}
+
+const char *TimeLoopModifier::getDefaultName() const {
+	return "TimeLoop Modifier"; // ???
+}
+
+ConductorModifier::ConductorModifier() {
+}
+
+ConductorModifier::~ConductorModifier() {
+}
+
+bool ConductorModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::ConductorModifier &data) {
+	return true;
+}
+
+bool ConductorModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState ConductorModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void ConductorModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void ConductorModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> ConductorModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new ConductorModifier(*this));
+}
+
+const char *ConductorModifier::getDefaultName() const {
+	return "Conductor Modifier"; // ???
+}
+
+AlphaMaticModifier::AlphaMaticModifier() {
+}
+
+AlphaMaticModifier::~AlphaMaticModifier() {
+}
+
+bool AlphaMaticModifier::load(const PlugInModifierLoaderContext &context, const Data::Thereware::AlphaMaticModifier &data) {
+	return true;
+}
+
+bool AlphaMaticModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState AlphaMaticModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void AlphaMaticModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void AlphaMaticModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> AlphaMaticModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new AlphaMaticModifier(*this));
+}
+
+const char *AlphaMaticModifier::getDefaultName() const {
+	return "AlphaMatic Modifier"; // ???
+}
+
+TherewarePlugIn::TherewarePlugIn()
+	: _conductorModifierFactory(this)
+	, _alphaMaticModifierFactory(this)
+	, _rotatorModifierFactory(this)
+	, _trackerModifierFactory(this)
+	, _doubleClickModifierFactory(this)
+	, _mouseTrapModifierFactory(this)
+	, _wrapAroundModifierFactory(this)
+	, _easyScrollerModifierFactory(this)
+	, _goThereModifierFactory(this)
+	, _randomizerModifierFactory(this)
+	, _timeLoopModifierFactory(this) {
+}
+
+TherewarePlugIn::~TherewarePlugIn() {
+}
+
+void TherewarePlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
+	//Alpha Kit
+	registrar->registerPlugInModifier("AlphaMatic", &_alphaMaticModifierFactory);
+
+	//Rotator Kit
+	registrar->registerPlugInModifier("Rotator", &_rotatorModifierFactory);
+	registrar->registerPlugInModifier("Tracker", &_trackerModifierFactory);
+
+	//Mercury Kit
+	registrar->registerPlugInModifier("DoubleClick", &_doubleClickModifierFactory);
+	registrar->registerPlugInModifier("MouseTrap", &_mouseTrapModifierFactory);
+	registrar->registerPlugInModifier("TimeLoop", &_timeLoopModifierFactory);
+
+	//WrapAround Kit
+	registrar->registerPlugInModifier("WrapAround", &_wrapAroundModifierFactory);
+	registrar->registerPlugInModifier("EasyScroller", &_easyScrollerModifierFactory);
+
+	//FixIt Kit
+	registrar->registerPlugInModifier("GoThere", &_goThereModifierFactory);
+
+	//Quick Kit
+	registrar->registerPlugInModifier("Randomizer", &_randomizerModifierFactory);
+	registrar->registerPlugInModifier("Conductor", &_conductorModifierFactory);
+}
+
+} // End of namespace Thereware
+
+namespace PlugIns {
+
+Common::SharedPtr<PlugIn> createThereware() {
+	return Common::SharedPtr<PlugIn>(new Thereware::TherewarePlugIn());
+}
+
+} // End of namespace PlugIns
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/thereware.h b/engines/mtropolis/plugin/thereware.h
new file mode 100644
index 00000000000..9b5b650eb02
--- /dev/null
+++ b/engines/mtropolis/plugin/thereware.h
@@ -0,0 +1,302 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_THEREWARE_H
+#define MTROPOLIS_PLUGIN_THEREWARE_H
+
+#include "mtropolis/modifiers.h"
+#include "mtropolis/modifier_factory.h"
+#include "mtropolis/runtime.h"
+#include "mtropolis/plugin/thereware_data.h"
+
+namespace MTropolis {
+
+namespace Thereware {
+
+class ConductorModifier : public Modifier {
+public:
+	ConductorModifier();
+	~ConductorModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::ConductorModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "Conductor Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class AlphaMaticModifier : public Modifier {
+public:
+	AlphaMaticModifier();
+	~AlphaMaticModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::AlphaMaticModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "AlphaMatic Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class RotatorModifier : public Modifier {
+public:
+	RotatorModifier();
+	~RotatorModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::RotatorModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "Rotator Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class TrackerModifier : public Modifier {
+public:
+	TrackerModifier();
+	~TrackerModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::TrackerModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "Tracker Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class MouseTrapModifier : public Modifier {
+public:
+	MouseTrapModifier();
+	~MouseTrapModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::MouseTrapModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "MouseTrap Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class DoubleClickModifier : public Modifier {
+public:
+	DoubleClickModifier();
+	~DoubleClickModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::DoubleClickModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "DoubleClick Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class WrapAroundModifier : public Modifier {
+public:
+	WrapAroundModifier();
+	~WrapAroundModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::WrapAroundModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "WrapAround Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class EasyScrollerModifier : public Modifier {
+public:
+	EasyScrollerModifier();
+	~EasyScrollerModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::EasyScrollerModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "EasyScroller Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class GoThereModifier : public Modifier {
+public:
+	GoThereModifier();
+	~GoThereModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::GoThereModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "GoThere Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class RandomizerModifier : public Modifier {
+public:
+	RandomizerModifier();
+	~RandomizerModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::RandomizerModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "Randomizer Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class TimeLoopModifier : public Modifier {
+public:
+	TimeLoopModifier();
+	~TimeLoopModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::Thereware::TimeLoopModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "TimeLoop Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+
+class TherewarePlugIn : public MTropolis::PlugIn {
+public:
+	TherewarePlugIn();
+	~TherewarePlugIn();
+
+	void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
+
+private:
+	PlugInModifierFactory<ConductorModifier, Data::Thereware::ConductorModifier> _conductorModifierFactory;
+	PlugInModifierFactory<AlphaMaticModifier, Data::Thereware::AlphaMaticModifier> _alphaMaticModifierFactory;
+	PlugInModifierFactory<RotatorModifier, Data::Thereware::RotatorModifier> _rotatorModifierFactory;
+	PlugInModifierFactory<TrackerModifier, Data::Thereware::TrackerModifier> _trackerModifierFactory;
+	PlugInModifierFactory<DoubleClickModifier, Data::Thereware::DoubleClickModifier> _doubleClickModifierFactory;
+	PlugInModifierFactory<MouseTrapModifier, Data::Thereware::MouseTrapModifier> _mouseTrapModifierFactory;
+	PlugInModifierFactory<WrapAroundModifier, Data::Thereware::WrapAroundModifier> _wrapAroundModifierFactory;
+	PlugInModifierFactory<EasyScrollerModifier, Data::Thereware::EasyScrollerModifier> _easyScrollerModifierFactory;
+	PlugInModifierFactory<GoThereModifier, Data::Thereware::GoThereModifier> _goThereModifierFactory;
+	PlugInModifierFactory<RandomizerModifier, Data::Thereware::RandomizerModifier> _randomizerModifierFactory;
+	PlugInModifierFactory<TimeLoopModifier, Data::Thereware::TimeLoopModifier> _timeLoopModifierFactory;
+};
+
+} // End of namespace Thereware
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/thereware_data.cpp b/engines/mtropolis/plugin/thereware_data.cpp
new file mode 100644
index 00000000000..f7fc0de1333
--- /dev/null
+++ b/engines/mtropolis/plugin/thereware_data.cpp
@@ -0,0 +1,183 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/thereware_data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace Thereware {
+
+DataReadErrorCode RotatorModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Event.load(reader) || !unknown3Bool.load(reader) || !unknown4Int.load(reader) || !unknown5Float.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Bool.load(reader) || !unknown7Point.load(reader) || !unknown8Int.load(reader) || !unknown9Bool.load(reader) || !unknown10Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown11Event.load(reader) || !unknown12Label.load(reader) || !unknown13Null.load(reader) || !unknown14Int.load(reader) || !unknown15Point.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown16Point.load(reader) || !unknown17Point.load(reader) || !unknown18Bool.load(reader) || !unknown19Point.load(reader) || !unknown20Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode TrackerModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Event.load(reader) || !unknown3Label.load(reader) || !unknown4Int.load(reader) || !unknown5Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Label.load(reader) || !unknown7Bool.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode DoubleClickModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1UniversalTime.load(reader) || !unknown2Event.load(reader) || !unknown3Event.load(reader) || !unknown4Null.load(reader) || !unknown5Label.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Int.load(reader) || !unknown7Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode MouseTrapModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1UniversalTime.load(reader) || !unknown2Event.load(reader) || !unknown3Event.load(reader) || !unknown4Event.load(reader) || !unknown5Null.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Label.load(reader) || !unknown7Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode WrapAroundModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 1)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Event.load(reader) || !unknown3Point.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown4Int.load(reader) || !unknown5Bool.load(reader) || !unknown6Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode EasyScrollerModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 1)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Event.load(reader) || !unknown3Int.load(reader) || !unknown4Int.load(reader) || !unknown5Label.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Int.load(reader) || !unknown7Int.load(reader) || !unknown8Int.load(reader) || !unknown9Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode TimeLoopModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Event.load(reader) || !unknown3Event.load(reader) || !unknown4Null.load(reader) || !unknown5Label.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Int.load(reader) || !unknown7Int.load(reader) || !unknown8UniversalTime.load(reader) || !unknown9Bool.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode GoThereModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 1)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Event.load(reader) || !unknown2Event.load(reader) || !unknown3Point.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown4UniversalTime.load(reader) || !unknown5Event.load(reader) || !unknown6Label.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown7Null.load(reader) || !unknown8Int.load(reader) || !unknown9Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown10Bool.load(reader) || !unknown11Bool.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode RandomizerModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 0)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Int.load(reader) || !unknown2Int.load(reader) || !unknown3Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode ConductorModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 1)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Null.load(reader) || !unknown2Null.load(reader) || !unknown3Int.load(reader) || !unknown4Null.load(reader) || !unknown5Null.load(reader))
+		return kDataReadErrorReadFailed;
+
+	if (!unknown6Null.load(reader) || !unknown7Event.load(reader) || !unknown8Null.load(reader) || !unknown9Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+DataReadErrorCode AlphaMaticModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 1)
+		return kDataReadErrorUnsupportedRevision;
+
+    error("Data structure loading for the AlphaMatic modifier is not implemented.");
+
+	return kDataReadErrorNone;
+}
+
+
+} // End of namespace Thereware
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/thereware_data.h b/engines/mtropolis/plugin/thereware_data.h
new file mode 100644
index 00000000000..81354458436
--- /dev/null
+++ b/engines/mtropolis/plugin/thereware_data.h
@@ -0,0 +1,184 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_THEREWARE_DATA_H
+#define MTROPOLIS_PLUGIN_THEREWARE_DATA_H
+
+#include "mtropolis/data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace Thereware {
+
+struct ConductorModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Null;
+	PlugInTypeTaggedValue unknown2Null;
+	PlugInTypeTaggedValue unknown3Int;
+	PlugInTypeTaggedValue unknown4Null;
+	PlugInTypeTaggedValue unknown5Null;
+	PlugInTypeTaggedValue unknown6Null;
+	PlugInTypeTaggedValue unknown7Event;
+	PlugInTypeTaggedValue unknown8Null;
+	PlugInTypeTaggedValue unknown9Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct AlphaMaticModifier : public PlugInModifierData {
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct RotatorModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Bool;
+	PlugInTypeTaggedValue unknown4Int;
+	PlugInTypeTaggedValue unknown5Float;
+	PlugInTypeTaggedValue unknown6Bool;
+	PlugInTypeTaggedValue unknown7Point;
+	PlugInTypeTaggedValue unknown8Int;
+	PlugInTypeTaggedValue unknown9Bool;
+	PlugInTypeTaggedValue unknown10Int;
+	PlugInTypeTaggedValue unknown11Event;
+	PlugInTypeTaggedValue unknown12Label;
+	PlugInTypeTaggedValue unknown13Null;
+	PlugInTypeTaggedValue unknown14Int;
+	PlugInTypeTaggedValue unknown15Point;
+	PlugInTypeTaggedValue unknown16Point;
+	PlugInTypeTaggedValue unknown17Point;
+	PlugInTypeTaggedValue unknown18Bool;
+	PlugInTypeTaggedValue unknown19Point;
+	PlugInTypeTaggedValue unknown20Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct TrackerModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Label;
+	PlugInTypeTaggedValue unknown4Int;
+	PlugInTypeTaggedValue unknown5Int;
+	PlugInTypeTaggedValue unknown6Label;
+	PlugInTypeTaggedValue unknown7Bool;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+
+struct DoubleClickModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1UniversalTime;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Event;
+	PlugInTypeTaggedValue unknown4Null;
+	PlugInTypeTaggedValue unknown5Label;
+	PlugInTypeTaggedValue unknown6Int;
+	PlugInTypeTaggedValue unknown7Int;
+
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct MouseTrapModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1UniversalTime;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Event;
+	PlugInTypeTaggedValue unknown4Event;
+	PlugInTypeTaggedValue unknown5Null;
+	PlugInTypeTaggedValue unknown6Label;
+	PlugInTypeTaggedValue unknown7Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct WrapAroundModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Point;
+	PlugInTypeTaggedValue unknown4Int;
+	PlugInTypeTaggedValue unknown5Bool;
+	PlugInTypeTaggedValue unknown6Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct EasyScrollerModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Int;
+	PlugInTypeTaggedValue unknown4Int;
+	PlugInTypeTaggedValue unknown5Label;
+	PlugInTypeTaggedValue unknown6Int;
+	PlugInTypeTaggedValue unknown7Int;
+	PlugInTypeTaggedValue unknown8Int;
+	PlugInTypeTaggedValue unknown9Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct TimeLoopModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Event;
+	PlugInTypeTaggedValue unknown4Null;
+	PlugInTypeTaggedValue unknown5Label;
+	PlugInTypeTaggedValue unknown6Int;
+	PlugInTypeTaggedValue unknown7Int;
+	PlugInTypeTaggedValue unknown8UniversalTime;
+	PlugInTypeTaggedValue unknown9Bool;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct GoThereModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Event;
+	PlugInTypeTaggedValue unknown2Event;
+	PlugInTypeTaggedValue unknown3Point;
+	PlugInTypeTaggedValue unknown4UniversalTime;
+	PlugInTypeTaggedValue unknown5Event;
+	PlugInTypeTaggedValue unknown6Label;
+	PlugInTypeTaggedValue unknown7Null;
+	PlugInTypeTaggedValue unknown8Int;
+	PlugInTypeTaggedValue unknown9Int;
+	PlugInTypeTaggedValue unknown10Bool;
+	PlugInTypeTaggedValue unknown11Bool;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+struct RandomizerModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Int;
+	PlugInTypeTaggedValue unknown2Int;
+	PlugInTypeTaggedValue unknown3Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+} // End of namespace Thereware
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugins.h b/engines/mtropolis/plugins.h
index bf009bea769..a42c79acfdc 100644
--- a/engines/mtropolis/plugins.h
+++ b/engines/mtropolis/plugins.h
@@ -42,6 +42,14 @@ Common::SharedPtr<PlugIn> createMIDI();
 Common::SharedPtr<PlugIn> createStandard();
 Common::SharedPtr<PlugIn> createObsidian(const Common::SharedPtr<Obsidian::WordGameData> &wgData);
 Common::SharedPtr<PlugIn> createMTI();
+Common::SharedPtr<PlugIn> createFTTS();
+
+Common::SharedPtr<PlugIn> createKnowWonder();
+
+Common::SharedPtr<PlugIn> createAXLogic();
+Common::SharedPtr<PlugIn> createHoologic();
+Common::SharedPtr<PlugIn> createMLine();
+Common::SharedPtr<PlugIn> createThereware();
 
 } // End of namespace PlugIns
 


Commit: 1ae5882baf7480e3b6ba039be4356a8ed6ab2ec4
    https://github.com/scummvm/scummvm/commit/1ae5882baf7480e3b6ba039be4356a8ed6ab2ec4
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
MTROPOLIS: add listings and descriptions of known modifiers

Changed paths:
    engines/mtropolis/plugin/axlogic_data.h
    engines/mtropolis/plugin/ftts_data.h
    engines/mtropolis/plugin/hoologic_data.h
    engines/mtropolis/plugin/kw_data.h
    engines/mtropolis/plugin/mline_data.h
    engines/mtropolis/plugin/thereware_data.h


diff --git a/engines/mtropolis/plugin/axlogic_data.h b/engines/mtropolis/plugin/axlogic_data.h
index 4cf1d542ae0..12c37c74957 100644
--- a/engines/mtropolis/plugin/axlogic_data.h
+++ b/engines/mtropolis/plugin/axlogic_data.h
@@ -30,6 +30,31 @@ namespace Data {
 
 namespace AXLogic {
 
+// Known AXLogic custom modifiers:
+//
+// * Quicktime Kit:
+// - AXImagePlayer
+// - AXQTVRMessenger
+// - AXQTVRNavigator
+// - PenguinPatch (???)
+//
+// * AlienLogic Kit: New scripting system as an alternative to Miniscript
+// - AXList
+// - AlienMathLib
+// - AlienMiscLib
+// - AlienObject
+// - AlienStringLib
+// - AlienWriter
+// - CodeExecuterACod
+// - CodeExecuterBase
+// - RuntimeExecute
+// - XCodeLibraryStnd
+//
+//   For mTropolis 1.1, the implementation of AlienLogic
+//   may be spread across multiple plugins
+//   But with the same modifiers
+
+
 struct AlienWriterModifier : public PlugInModifierData {
 protected:
 	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
diff --git a/engines/mtropolis/plugin/ftts_data.h b/engines/mtropolis/plugin/ftts_data.h
index 81d75298c21..7a7863ea17a 100644
--- a/engines/mtropolis/plugin/ftts_data.h
+++ b/engines/mtropolis/plugin/ftts_data.h
@@ -30,6 +30,11 @@ namespace Data {
 
 namespace FTTS {
 
+// Known Fairy Tale: A True Story - Activity Center custom modifiers:
+// - Motion
+// - Sparke
+
+
 struct MotionModifier : public PlugInModifierData {
 	PlugInTypeTaggedValue unknown1Event;
 	PlugInTypeTaggedValue unknown2Event;
diff --git a/engines/mtropolis/plugin/hoologic_data.h b/engines/mtropolis/plugin/hoologic_data.h
index 29a82d2e8cd..2e6ee8ec3bd 100644
--- a/engines/mtropolis/plugin/hoologic_data.h
+++ b/engines/mtropolis/plugin/hoologic_data.h
@@ -30,6 +30,26 @@ namespace Data {
 
 namespace Hoologic {
 
+// Known Hoologic custom modifiers:
+// * Bitmap Suite
+// - hlBitmapVariable: variable storing a bitmap
+// - hlCaptureBitmap: captures a screen image into a bitmap
+// - hlPrintBitmap: print a bitmap
+// - hlSaveBitmap: saves a bitmap as a PICT/BMP file
+// - hlImportBitamp: load a bitmap from a PICT/BMP file
+// - hlDisplayBitmap: display a bitmap
+// - hlScaleBitmap: scale a bitmap
+//
+// * Painter Plugin
+// - hlPainter: Creates painting effects and interaction by blending several pictures together
+//
+// * KeyState Plugin
+// - hlKeyState: State of keyboard keys, and if modifier keys (CTRL, SHIFT, ...) are used?
+//
+// * AppleScript Suite
+// - ???
+
+
 struct BitmapVariableModifier : public PlugInModifierData {
 protected:
 	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
diff --git a/engines/mtropolis/plugin/kw_data.h b/engines/mtropolis/plugin/kw_data.h
index c5ad100df18..aa81c5b18d8 100644
--- a/engines/mtropolis/plugin/kw_data.h
+++ b/engines/mtropolis/plugin/kw_data.h
@@ -30,6 +30,13 @@ namespace Data {
 
 namespace KW {
 
+//
+// Known KnowWonder custom modifiers:
+// - IdxIter
+// - StrUtil
+// - TicTacToe
+
+
 struct StrUtilModifier : public PlugInModifierData {
 protected:
 	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
diff --git a/engines/mtropolis/plugin/mline_data.h b/engines/mtropolis/plugin/mline_data.h
index 18f6e5472c9..ae42962801e 100644
--- a/engines/mtropolis/plugin/mline_data.h
+++ b/engines/mtropolis/plugin/mline_data.h
@@ -30,6 +30,14 @@ namespace Data {
 
 namespace MLine {
 
+// Known mLine custom modifiers:
+// * Launchme
+// - URLLaunch: Launch/Open external files and applications
+//
+// * Database
+// - Database (???)
+
+
 struct MLineLauncherModifier : public PlugInModifierData {
 	PlugInTypeTaggedValue unknown1String;
 	PlugInTypeTaggedValue unknown2String;
diff --git a/engines/mtropolis/plugin/thereware_data.h b/engines/mtropolis/plugin/thereware_data.h
index 81354458436..21088a740c2 100644
--- a/engines/mtropolis/plugin/thereware_data.h
+++ b/engines/mtropolis/plugin/thereware_data.h
@@ -30,6 +30,59 @@ namespace Data {
 
 namespace Thereware {
 
+// Known Thereware custom modifiers:
+// * Alpha Kit:
+// - Alpha: Alpha channel support for graphics and mToons
+// - AlphaMatic: Automatically creates alpha information on graphics
+//
+// * HotText Kit:
+// - HotText: Hypertext and scrolling text
+// - KeyScroll: Keyboard scrolling for HotText
+//
+// * Spinner Kit:
+// - Spinner: Effect for spinning an element with depth/two-sidedness
+// - TurnOver: Like spinner, but specifically for 180 degree spins
+// - Flipper: reflect graphics elements around horizontal or vertical axis
+// - Squish: Squishing and elasticity for images
+//
+// * Rotator Kit:
+// - Rotator: Rotation of graphics and mToons
+// - Tracker: Track mouse or elements as a rotation angle source
+//
+// * WrapAround Kit:
+// - WrapAround: wraparound effect for graphics and mToons
+// - EasyScroller: various detail controls for scrolling behavior
+//
+// * Quick Kit:
+// - Flasher: Lets objects blinko on the screen
+// - Snapper: Creates an invisible grid that elements can snap onto when dragged
+// - Conductor: Forward messages to all the children of an element
+// - Randomizer: Use random numbers without Miniscript
+//
+// * Mercury Kit:
+// - DoubleClick: Messages on doubleclick. Can also do the same as the Counter messenger.
+// - MouseTrap: Blocks/filters messages for a certain time period.
+// - RandomTimer: Allows Miniscript altercations to the Timer messenger
+//   Same as FlexiTimer in FixIt Kit
+// - Repeater: Timer messenger that adds a certain delay before looping 
+// - Counter: Sends a message after a certain number of incoming messages
+// - TimeLoop: Sends message a certain number of times
+//
+// * System Kit:
+// - Platform: Indicates computer type and OS
+//
+// * FixIt Kit:
+// - GoThere: Moves an element to an arbitrary point on the screen. 
+//   Superceded by the Point Motion modifier in mTropolis 2.0.
+// - FlexiTimer: Allows Miniscript altercations to the Timer messenger
+//	 Same as RandomTimer in Mercury Kit
+//
+//
+// While those Kits were available individually, for mTropolis 2.0
+// they were also available as a complete bundle in a single plugin,
+// the Thereware Pro Kit.
+
+
 struct ConductorModifier : public PlugInModifierData {
 	PlugInTypeTaggedValue unknown1Null;
 	PlugInTypeTaggedValue unknown2Null;


Commit: 7656dbab4459bf5027dd045a3d7cc07ffec4bfeb
    https://github.com/scummvm/scummvm/commit/7656dbab4459bf5027dd045a3d7cc07ffec4bfeb
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
MTROPOLIS: fixes to include guards

Changed paths:
    engines/mtropolis/plugin/hoologic_data.h
    engines/mtropolis/plugin/mline_data.h


diff --git a/engines/mtropolis/plugin/hoologic_data.h b/engines/mtropolis/plugin/hoologic_data.h
index 2e6ee8ec3bd..2533ee38c3c 100644
--- a/engines/mtropolis/plugin/hoologic_data.h
+++ b/engines/mtropolis/plugin/hoologic_data.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef MTROPOLIS_PLUGIN_Hoologic_DATA_H
-#define MTROPOLIS_PLUGIN_Hoologic_DATA_H
+#ifndef MTROPOLIS_PLUGIN_HOOLOGIC_DATA_H
+#define MTROPOLIS_PLUGIN_HOOLOGIC_DATA_H
 
 #include "mtropolis/data.h"
 
diff --git a/engines/mtropolis/plugin/mline_data.h b/engines/mtropolis/plugin/mline_data.h
index ae42962801e..dc988bbaa67 100644
--- a/engines/mtropolis/plugin/mline_data.h
+++ b/engines/mtropolis/plugin/mline_data.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef MTROPOLIS_PLUGIN_FTTS_DATA_H
-#define MTROPOLIS_PLUGIN_FTTS_DATA_H
+#ifndef MTROPOLIS_PLUGIN_MLINE_DATA_H
+#define MTROPOLIS_PLUGIN_MLINE_DATA_H
 
 #include "mtropolis/data.h"
 


Commit: 31ff64b2763c5845c8dbeef541163c6e4c85841d
    https://github.com/scummvm/scummvm/commit/31ff64b2763c5845c8dbeef541163c6e4c85841d
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
MTROPOLIS: add stubs for RWC plugin

The title "Real Wild Child! Australian Rock Music 1950s-90s" has custom modifiers that will need their own plugin.

Changed paths:
  A engines/mtropolis/plugin/rwc.cpp
  A engines/mtropolis/plugin/rwc.h
  A engines/mtropolis/plugin/rwc_data.cpp
  A engines/mtropolis/plugin/rwc_data.h
    engines/mtropolis/boot.cpp
    engines/mtropolis/module.mk
    engines/mtropolis/plugins.h


diff --git a/engines/mtropolis/boot.cpp b/engines/mtropolis/boot.cpp
index 3c06690b496..571e4ec55ec 100644
--- a/engines/mtropolis/boot.cpp
+++ b/engines/mtropolis/boot.cpp
@@ -1079,6 +1079,7 @@ public:
 		kPlugInObsidian,
 		kPlugInMIDI,
 		kPlugInFTTS,
+		kPlugInRWC,
 		kPlugInKnowWonder,
 		kPlugInAxLogic,
 		kPlugInHoologic,
@@ -1473,6 +1474,7 @@ void BootScriptContext::executeFunction(const Common::String &functionName, cons
 									  ENUM_BINDING(kPlugInObsidian),
 									  ENUM_BINDING(kPlugInMIDI),
 									  ENUM_BINDING(kPlugInFTTS),
+									  ENUM_BINDING(kPlugInRWC),
 									  ENUM_BINDING(kPlugInKnowWonder),
 									  ENUM_BINDING(kPlugInAxLogic),
 									  ENUM_BINDING(kPlugInHoologic),
@@ -2124,6 +2126,11 @@ Common::SharedPtr<MTropolis::PlugIn> loadFTTSPlugIn(const MTropolisGameDescripti
 	return fttsPlugIn;
 }
 
+Common::SharedPtr<MTropolis::PlugIn> loadRWCPlugIn(const MTropolisGameDescription &gameDesc) {
+	Common::SharedPtr<MTropolis::PlugIn> rwcPlugIn(PlugIns::createRWC());
+	return rwcPlugIn;
+}
+
 Common::SharedPtr<MTropolis::PlugIn> loadKnowWonderPlugIn(const MTropolisGameDescription &gameDesc) {
 	Common::SharedPtr<MTropolis::PlugIn> kwPlugIn(PlugIns::createKnowWonder());
 	return kwPlugIn;
@@ -3025,6 +3032,9 @@ BootConfiguration bootProject(const MTropolisGameDescription &gameDesc) {
 		case Boot::BootScriptContext::kPlugInFTTS:
 			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
 			break;
+		case Boot::BootScriptContext::kPlugInRWC:
+			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			break;
 		case Boot::BootScriptContext::kPlugInKnowWonder:
 			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
 			break;
diff --git a/engines/mtropolis/module.mk b/engines/mtropolis/module.mk
index d6e5d749b04..279cda7c227 100644
--- a/engines/mtropolis/module.mk
+++ b/engines/mtropolis/module.mk
@@ -35,6 +35,8 @@ MODULE_OBJS = \
 	plugin/mti_data.o \
 	plugin/obsidian.o \
 	plugin/obsidian_data.o \
+	plugin/rwc.o \
+	plugin/rwc_data.o \
 	plugin/standard.o \
 	plugin/standard_data.o \
 	plugin/thereware.o \
diff --git a/engines/mtropolis/plugin/rwc.cpp b/engines/mtropolis/plugin/rwc.cpp
new file mode 100644
index 00000000000..4e7ccc28a3b
--- /dev/null
+++ b/engines/mtropolis/plugin/rwc.cpp
@@ -0,0 +1,86 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/rwc.h"
+#include "mtropolis/plugins.h"
+
+namespace MTropolis {
+
+namespace RWC {
+
+ThighBlasterModifier::ThighBlasterModifier() {
+}
+
+ThighBlasterModifier::~ThighBlasterModifier() {
+}
+
+bool ThighBlasterModifier::load(const PlugInModifierLoaderContext &context, const Data::RWC::ThighBlasterModifier &data) {
+	return true;
+}
+
+bool ThighBlasterModifier::respondsToEvent(const Event &evt) const {
+	return false;
+}
+
+VThreadState ThighBlasterModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
+	return kVThreadReturn;
+}
+
+void ThighBlasterModifier::disable(Runtime *runtime) {
+}
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+void ThighBlasterModifier::debugInspect(IDebugInspectionReport *report) const {
+	Modifier::debugInspect(report);
+}
+#endif
+
+Common::SharedPtr<Modifier> ThighBlasterModifier::shallowClone() const {
+	return Common::SharedPtr<Modifier>(new ThighBlasterModifier(*this));
+}
+
+const char *ThighBlasterModifier::getDefaultName() const {
+	return "mLine Launcher Modifier"; // ???
+}
+
+RWCPlugIn::RWCPlugIn()
+	: _thighBlasterModifierFactory(this) {
+}
+
+RWCPlugIn::~RWCPlugIn() {
+}
+
+void RWCPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
+	//URLaunch modifier by mLine
+	registrar->registerPlugInModifier("ThighBlaster", &_thighBlasterModifierFactory);
+}
+
+} // End of namespace RWC
+
+namespace PlugIns {
+
+Common::SharedPtr<PlugIn> createRWC() {
+	return Common::SharedPtr<PlugIn>(new RWC::RWCPlugIn());
+}
+
+} // End of namespace PlugIns
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/rwc.h b/engines/mtropolis/plugin/rwc.h
new file mode 100644
index 00000000000..ec30498f38d
--- /dev/null
+++ b/engines/mtropolis/plugin/rwc.h
@@ -0,0 +1,71 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_RWC_H
+#define MTROPOLIS_PLUGIN_RWC_H
+
+#include "mtropolis/modifiers.h"
+#include "mtropolis/modifier_factory.h"
+#include "mtropolis/runtime.h"
+#include "mtropolis/plugin/rwc_data.h"
+
+namespace MTropolis {
+
+namespace RWC {
+
+class ThighBlasterModifier : public Modifier {
+public:
+	ThighBlasterModifier();
+	~ThighBlasterModifier();
+
+	bool load(const PlugInModifierLoaderContext &context, const Data::RWC::ThighBlasterModifier &data);
+
+	bool respondsToEvent(const Event &evt) const override;
+	VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
+
+	void disable(Runtime *runtime) override;
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+	const char *debugGetTypeName() const override { return "ThighBlaster Modifier"; }
+	void debugInspect(IDebugInspectionReport *report) const override;
+#endif
+
+private:
+	Common::SharedPtr<Modifier> shallowClone() const override;
+	const char *getDefaultName() const override;
+};
+
+class RWCPlugIn : public MTropolis::PlugIn {
+public:
+	RWCPlugIn();
+	~RWCPlugIn();
+
+	void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
+
+private:
+	PlugInModifierFactory<ThighBlasterModifier, Data::RWC::ThighBlasterModifier> _thighBlasterModifierFactory;
+};
+
+} // End of namespace RWC
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugin/rwc_data.cpp b/engines/mtropolis/plugin/rwc_data.cpp
new file mode 100644
index 00000000000..8e4d4e28ddc
--- /dev/null
+++ b/engines/mtropolis/plugin/rwc_data.cpp
@@ -0,0 +1,44 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mtropolis/plugin/rwc_data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace RWC {
+
+DataReadErrorCode ThighBlasterModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
+	if (prefix.plugInRevision != 1)
+		return kDataReadErrorUnsupportedRevision;
+
+	if (!unknown1Int.load(reader))
+		return kDataReadErrorReadFailed;
+
+	return kDataReadErrorNone;
+}
+
+} // End of namespace RWC
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/rwc_data.h b/engines/mtropolis/plugin/rwc_data.h
new file mode 100644
index 00000000000..5452246bb6c
--- /dev/null
+++ b/engines/mtropolis/plugin/rwc_data.h
@@ -0,0 +1,52 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MTROPOLIS_PLUGIN_MLINE_DATA_H
+#define MTROPOLIS_PLUGIN_MLINE_DATA_H
+
+#include "mtropolis/data.h"
+
+namespace MTropolis {
+
+namespace Data {
+
+namespace RWC {
+
+// Known Real Wild Child! Australian Rock Music 1950s-90s custom modifiers:
+// - Invalidate
+// - Ripple
+// - Spraycan
+// - ThighBlaster
+
+
+struct ThighBlasterModifier : public PlugInModifierData {
+	PlugInTypeTaggedValue unknown1Int;
+protected:
+	DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
+};
+
+} // End of namespace RWC
+
+} // End of namespace Data
+
+} // End of namespace MTropolis
+
+#endif
diff --git a/engines/mtropolis/plugins.h b/engines/mtropolis/plugins.h
index a42c79acfdc..20a5b490a34 100644
--- a/engines/mtropolis/plugins.h
+++ b/engines/mtropolis/plugins.h
@@ -43,6 +43,7 @@ Common::SharedPtr<PlugIn> createStandard();
 Common::SharedPtr<PlugIn> createObsidian(const Common::SharedPtr<Obsidian::WordGameData> &wgData);
 Common::SharedPtr<PlugIn> createMTI();
 Common::SharedPtr<PlugIn> createFTTS();
+Common::SharedPtr<PlugIn> createRWC();
 
 Common::SharedPtr<PlugIn> createKnowWonder();
 


Commit: 86d368472811463be8daea516a196610e0427541
    https://github.com/scummvm/scummvm/commit/86d368472811463be8daea516a196610e0427541
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
MTROPOLIS: fix mapping of plugin enum to functions

Resolve copypaste error

Changed paths:
    engines/mtropolis/boot.cpp


diff --git a/engines/mtropolis/boot.cpp b/engines/mtropolis/boot.cpp
index 571e4ec55ec..40a3b595760 100644
--- a/engines/mtropolis/boot.cpp
+++ b/engines/mtropolis/boot.cpp
@@ -3030,25 +3030,25 @@ BootConfiguration bootProject(const MTropolisGameDescription &gameDesc) {
 			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
 			break;
 		case Boot::BootScriptContext::kPlugInFTTS:
-			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			plugIns.push_back(Boot::loadFTTSPlugIn(gameDesc));
 			break;
 		case Boot::BootScriptContext::kPlugInRWC:
-			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			plugIns.push_back(Boot::loadRWCPlugIn(gameDesc));
 			break;
 		case Boot::BootScriptContext::kPlugInKnowWonder:
-			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			plugIns.push_back(Boot::loadKnowWonderPlugIn(gameDesc));
 			break;
 		case Boot::BootScriptContext::kPlugInAxLogic:
-			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			plugIns.push_back(Boot::loadAXLogicPlugIn(gameDesc));
 			break;
 		case Boot::BootScriptContext::kPlugInHoologic:
-			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			plugIns.push_back(Boot::loadHoologicPlugIn(gameDesc));
 			break;
 		case Boot::BootScriptContext::kPlugInMLine:
-			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			plugIns.push_back(Boot::loadMLinePlugIn(gameDesc));
 			break;
 		case Boot::BootScriptContext::kPlugInThereware:
-			plugIns.push_back(Boot::loadMTIPlugIn(gameDesc));
+			plugIns.push_back(Boot::loadTherewarePlugIn(gameDesc));
 			break;
 		default:
 			error("Unknown plug-in ID");


Commit: b6cf098daa5d770ba46c9232a909ac78fc194192
    https://github.com/scummvm/scummvm/commit/b6cf098daa5d770ba46c9232a909ac78fc194192
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
JANITORIAL: corrections to comments

Changed paths:
    engines/mtropolis/plugin/mline.cpp
    engines/mtropolis/plugin/rwc.cpp


diff --git a/engines/mtropolis/plugin/mline.cpp b/engines/mtropolis/plugin/mline.cpp
index 4db9e2090b0..fcfad5eb011 100644
--- a/engines/mtropolis/plugin/mline.cpp
+++ b/engines/mtropolis/plugin/mline.cpp
@@ -69,7 +69,7 @@ MLinePlugIn::~MLinePlugIn() {
 }
 
 void MLinePlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
-	//URLaunch modifier by mLine
+	//URLaunch plugin by mLine
 	registrar->registerPlugInModifier("mLine_launcher", &_mlineLauncherModifierFactory);
 }
 
diff --git a/engines/mtropolis/plugin/rwc.cpp b/engines/mtropolis/plugin/rwc.cpp
index 4e7ccc28a3b..35ca17c36df 100644
--- a/engines/mtropolis/plugin/rwc.cpp
+++ b/engines/mtropolis/plugin/rwc.cpp
@@ -69,7 +69,6 @@ RWCPlugIn::~RWCPlugIn() {
 }
 
 void RWCPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
-	//URLaunch modifier by mLine
 	registrar->registerPlugInModifier("ThighBlaster", &_thighBlasterModifierFactory);
 }
 


Commit: 0fa1add800c06ac82bb592c265fadec9e6692c4c
    https://github.com/scummvm/scummvm/commit/0fa1add800c06ac82bb592c265fadec9e6692c4c
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
MTROPOLIS: Use correct name in name string of ThighBlaster modifier

Copypaste error

Changed paths:
    engines/mtropolis/plugin/rwc.cpp


diff --git a/engines/mtropolis/plugin/rwc.cpp b/engines/mtropolis/plugin/rwc.cpp
index 35ca17c36df..bf007ed3011 100644
--- a/engines/mtropolis/plugin/rwc.cpp
+++ b/engines/mtropolis/plugin/rwc.cpp
@@ -58,7 +58,7 @@ Common::SharedPtr<Modifier> ThighBlasterModifier::shallowClone() const {
 }
 
 const char *ThighBlasterModifier::getDefaultName() const {
-	return "mLine Launcher Modifier"; // ???
+	return "ThighBlaster Modifier"; // ???
 }
 
 RWCPlugIn::RWCPlugIn()


Commit: f610969edb3e52586b5400d05e37abee2124b8da
    https://github.com/scummvm/scummvm/commit/f610969edb3e52586b5400d05e37abee2124b8da
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
JANITORIAL: use tabs for indentation

Changed paths:
    engines/mtropolis/plugin/axlogic_data.cpp
    engines/mtropolis/plugin/hoologic_data.cpp
    engines/mtropolis/plugin/thereware_data.cpp


diff --git a/engines/mtropolis/plugin/axlogic_data.cpp b/engines/mtropolis/plugin/axlogic_data.cpp
index cb521d2a191..44b95b31f74 100644
--- a/engines/mtropolis/plugin/axlogic_data.cpp
+++ b/engines/mtropolis/plugin/axlogic_data.cpp
@@ -31,7 +31,7 @@ DataReadErrorCode AlienWriterModifier::load(PlugIn &plugIn, const PlugInModifier
 	if (prefix.plugInRevision != 1)
 		return kDataReadErrorUnsupportedRevision;
 
-    error("Data structure loading for the AlienWriter modifier is not implemented.");
+	error("Data structure loading for the AlienWriter modifier is not implemented.");
 
 	return kDataReadErrorNone;
 }
diff --git a/engines/mtropolis/plugin/hoologic_data.cpp b/engines/mtropolis/plugin/hoologic_data.cpp
index 5fa2f7091d1..68a42dddcde 100644
--- a/engines/mtropolis/plugin/hoologic_data.cpp
+++ b/engines/mtropolis/plugin/hoologic_data.cpp
@@ -103,7 +103,7 @@ DataReadErrorCode PainterModifier::load(PlugIn &plugIn, const PlugInModifier &pr
 	if (prefix.plugInRevision != 0)
 		return kDataReadErrorUnsupportedRevision;
 
-    error("Data structure loading for the Painter modifier is not implemented.");
+	error("Data structure loading for the Painter modifier is not implemented.");
 
 	return kDataReadErrorNone;
 }
diff --git a/engines/mtropolis/plugin/thereware_data.cpp b/engines/mtropolis/plugin/thereware_data.cpp
index f7fc0de1333..a2f8558b4fe 100644
--- a/engines/mtropolis/plugin/thereware_data.cpp
+++ b/engines/mtropolis/plugin/thereware_data.cpp
@@ -170,7 +170,7 @@ DataReadErrorCode AlphaMaticModifier::load(PlugIn &plugIn, const PlugInModifier
 	if (prefix.plugInRevision != 1)
 		return kDataReadErrorUnsupportedRevision;
 
-    error("Data structure loading for the AlphaMatic modifier is not implemented.");
+	error("Data structure loading for the AlphaMatic modifier is not implemented.");
 
 	return kDataReadErrorNone;
 }


Commit: 453d85b33dfddb6b49cbd58fae3e6926abf5703b
    https://github.com/scummvm/scummvm/commit/453d85b33dfddb6b49cbd58fae3e6926abf5703b
Author: Michael (michael_kuerbis at web.de)
Date: 2024-09-04T20:04:49-04:00

Commit Message:
JANITORIAL: remove redundant commented out code

Changed paths:
    engines/mtropolis/plugin/hoologic.h


diff --git a/engines/mtropolis/plugin/hoologic.h b/engines/mtropolis/plugin/hoologic.h
index 82a6299cbae..a27a11db782 100644
--- a/engines/mtropolis/plugin/hoologic.h
+++ b/engines/mtropolis/plugin/hoologic.h
@@ -219,8 +219,6 @@ public:
 
 	void disable(Runtime *runtime) override;
 
-	// bool isVariable() const override { return true; }
-
 #ifdef MTROPOLIS_DEBUG_ENABLE
 	const char *debugGetTypeName() const override { return "KeyState Modifier"; }
 	void debugInspect(IDebugInspectionReport *report) const override;




More information about the Scummvm-git-logs mailing list