[Scummvm-git-logs] scummvm master -> 7d7e17868da009a6f54ef25dbc031188c485cf86

elasota noreply at scummvm.org
Sun Jul 3 02:03:37 UTC 2022


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

Summary:
7d7e17868d MTROPOLIS: Fix up dynamic MIDI option, add hack to skip corrupted video frame


Commit: 7d7e17868da009a6f54ef25dbc031188c485cf86
    https://github.com/scummvm/scummvm/commit/7d7e17868da009a6f54ef25dbc031188c485cf86
Author: elasota (ejlasota at gmail.com)
Date: 2022-07-02T22:03:00-04:00

Commit Message:
MTROPOLIS: Fix up dynamic MIDI option, add hack to skip corrupted video frame

Changed paths:
    engines/mtropolis/assets.cpp
    engines/mtropolis/assets.h
    engines/mtropolis/boot.cpp
    engines/mtropolis/detection.cpp
    engines/mtropolis/elements.cpp
    engines/mtropolis/elements.h
    engines/mtropolis/hacks.cpp
    engines/mtropolis/hacks.h
    engines/mtropolis/mtropolis.cpp
    engines/mtropolis/plugin/standard.cpp
    engines/mtropolis/plugin/standard.h
    engines/mtropolis/runtime.cpp
    engines/mtropolis/runtime.h


diff --git a/engines/mtropolis/assets.cpp b/engines/mtropolis/assets.cpp
index b2a4733322e..4d70e12b0f3 100644
--- a/engines/mtropolis/assets.cpp
+++ b/engines/mtropolis/assets.cpp
@@ -34,6 +34,12 @@
 
 namespace MTropolis {
 
+AssetHooks::~AssetHooks() {
+}
+
+void AssetHooks::onLoaded(Asset *asset, const Common::String &name) {
+}
+
 Asset::Asset() : _assetID(0) {
 }
 
@@ -739,6 +745,14 @@ size_t MovieAsset::getStreamIndex() const {
 	return _streamIndex;
 }
 
+void MovieAsset::addDamagedFrame(int frame) {
+	_damagedFrames.push_back(frame);
+}
+
+const Common::Array<int> &MovieAsset::getDamagedFrames() const {
+	return _damagedFrames;
+}
+
 
 CachedImage::CachedImage() : _colorDepth(kColorDepthModeInvalid), _isOptimized(false) {
 }
diff --git a/engines/mtropolis/assets.h b/engines/mtropolis/assets.h
index 7a06c3aae25..6148ca38b9a 100644
--- a/engines/mtropolis/assets.h
+++ b/engines/mtropolis/assets.h
@@ -206,6 +206,9 @@ public:
 	const Common::String &getExtFileName() const;
 	size_t getStreamIndex() const;
 
+	void addDamagedFrame(int frame);
+	const Common::Array<int> &getDamagedFrames() const;
+
 private:
 	uint32 _movieDataPos;
 	uint32 _moovAtomPos;
@@ -213,6 +216,8 @@ private:
 
 	Common::String _extFileName;
 	size_t _streamIndex;
+
+	Common::Array<int> _damagedFrames;
 };
 
 class CachedImage {
diff --git a/engines/mtropolis/boot.cpp b/engines/mtropolis/boot.cpp
index e40c144a3c4..edc7414cd32 100644
--- a/engines/mtropolis/boot.cpp
+++ b/engines/mtropolis/boot.cpp
@@ -136,6 +136,8 @@ private:
 	bool _isRetail;
 	bool _isEnglish;
 
+	bool _useDynamicMidi;
+
 	void unpackMacRetailInstaller(Common::Array<Common::SharedPtr<ProjectPersistentResource> > &persistentResources, Common::Array<FileIdentification> &files);
 	Common::SharedPtr<Obsidian::WordGameData> loadWinWordGameData();
 	Common::SharedPtr<Obsidian::WordGameData> loadMacWordGameData();
diff --git a/engines/mtropolis/detection.cpp b/engines/mtropolis/detection.cpp
index 92397f71ca0..e0c67921ef2 100644
--- a/engines/mtropolis/detection.cpp
+++ b/engines/mtropolis/detection.cpp
@@ -84,7 +84,7 @@ const ExtraGuiOptions MTropolisMetaEngineDetection::getExtraGuiOptions(const Com
 		_s("Improved Music Mixing"),
 		_s("Enables dynamic MIDI mixer, improving quality, but behaving less like mTropolis Player."),
 		"mtropolis_mod_dynamic_midi",
-		false,
+		true,
 		0,
 		0};
 
diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index aab9c98c3ea..6004d12eccd 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -684,6 +684,7 @@ void MovieElement::activate() {
 	qtDecoder->setVolume(_volume * 255 / 100);
 
 	_videoDecoder.reset(qtDecoder);
+	_damagedFrames = movieAsset->getDamagedFrames();
 
 	Common::SafeSeekableSubReadStream *movieDataStream = new Common::SafeSeekableSubReadStream(stream, movieAsset->getMovieDataPos(), movieAsset->getMovieDataPos() + movieAsset->getMovieDataSize(), DisposeAfterUse::NO);
 
@@ -794,6 +795,21 @@ void MovieElement::playMedia(Runtime *runtime, Project *project) {
 				if (_playEveryFrame && framesDecodedThisFrame > 0)
 					break;
 
+				if (_damagedFrames.size()) {
+					bool frameIsDamaged = false;
+					int thisFrameNumber = _videoDecoder->getCurFrame() + framesDecodedThisFrame + 1;
+
+					for (int damagedFrame : _damagedFrames) {
+						if (static_cast<int>(damagedFrame) == thisFrameNumber) {
+							frameIsDamaged = true;
+							break;
+						}
+					}
+
+					if (frameIsDamaged)
+						_videoDecoder->seekToFrame(thisFrameNumber + 1);
+				}
+
 				const Graphics::Surface *decodedFrame = _videoDecoder->decodeNextFrame();
 
 				// QuickTimeDecoder doesn't return true for endOfVideo or false for needsUpdate until it
diff --git a/engines/mtropolis/elements.h b/engines/mtropolis/elements.h
index 94ca52902d3..dbfb78d59f6 100644
--- a/engines/mtropolis/elements.h
+++ b/engines/mtropolis/elements.h
@@ -145,6 +145,8 @@ private:
 	Common::SharedPtr<SegmentUnloadSignaller> _unloadSignaller;
 	Common::SharedPtr<PlayMediaSignaller> _playMediaSignaller;
 
+	Common::Array<int> _damagedFrames;
+
 	Runtime *_runtime;
 };
 
diff --git a/engines/mtropolis/hacks.cpp b/engines/mtropolis/hacks.cpp
index 3f44926f71d..a9e63161532 100644
--- a/engines/mtropolis/hacks.cpp
+++ b/engines/mtropolis/hacks.cpp
@@ -21,6 +21,7 @@
 
 #include "common/system.h"
 
+#include "mtropolis/assets.h"
 #include "mtropolis/detection.h"
 #include "mtropolis/hacks.h"
 #include "mtropolis/runtime.h"
@@ -29,36 +30,36 @@ namespace MTropolis {
 
 Hacks::Hacks() {
 	ignoreMismatchedProjectNameInObjectLookups = false;
-
-	// reportDisplaySize set by Common::Point constructor
-	// mainWindowOffset set by Common::Point constructor
-
-	structuralHooks = nullptr;
-	modifierHooks = nullptr;
 }
 
 Hacks::~Hacks() {
-	if (structuralHooks)
-		delete structuralHooks;
-	if (modifierHooks)
-		delete modifierHooks;
 }
 
 void Hacks::addStructuralHooks(uint32 guid, const Common::SharedPtr<StructuralHooks> &hooks) {
-	if (!structuralHooks)
-		structuralHooks = new Common::HashMap<uint32, Common::SharedPtr<StructuralHooks> >();
-	(*structuralHooks)[guid] = hooks;
+	structuralHooks[guid] = hooks;
 }
 
 void Hacks::addModifierHooks(uint32 guid, const Common::SharedPtr<ModifierHooks> &hooks) {
-	if (!modifierHooks)
-		modifierHooks = new Common::HashMap<uint32, Common::SharedPtr<ModifierHooks> >();
-	(*modifierHooks)[guid] = hooks;
+	modifierHooks[guid] = hooks;
 }
 
+void Hacks::addAssetHooks(const Common::SharedPtr<AssetHooks> &hooks) {
+	assetHooks.push_back(hooks);
+}
 
 namespace HackSuites {
 
+class ObsidianCorruptedAirTowerTransitionFix : public AssetHooks {
+public:
+	void onLoaded(Asset *asset, const Common::String &name) override;
+};
+
+void ObsidianCorruptedAirTowerTransitionFix::onLoaded(Asset *asset, const Common::String &name) {
+	if (asset->getAssetType() == kAssetTypeMovie && name == "A105_132.01Fxx.trn") {
+		static_cast<MovieAsset *>(asset)->addDamagedFrame(35);
+	}
+}
+
 class ObsidianInventoryWindscreenHooks : public StructuralHooks {
 public:
 	void onSetPosition(Structural *structural, Common::Point &pt) override;
@@ -74,6 +75,23 @@ void ObsidianInventoryWindscreenHooks::onSetPosition(Structural *structural, Com
 	}
 }
 
+void addObsidianBugFixes(const MTropolisGameDescription &desc, Hacks &hacks) {
+	// Workaround for bug in Obsidian:
+	// When opening the journal in the intro, a script checks if cGSt.cfst.binjournal is false and if so,
+	// sets cGSt.cfst.binjournal to true and then sets including setting cJournalConst.aksjournpath to the
+	// main journal scene path.  That scene path is used to resolve the scene to go to after clicking
+	// the "Continue" button on the warning that pops up.
+	//
+	// The problem is that cJournalConst uses a project name that doesn't match the retail data, and
+	// cJournalConst is unloaded if the player leaves the journal.  This causes a progression blocker if
+	// the player leaves the journal without clicking Continue.
+	hacks.ignoreMismatchedProjectNameInObjectLookups = true;
+
+	// Fix for corrupted frame in transition from the outer edge in Spider to the air puzzle tower.
+	// The data is corrupted in both Mac and Win retail versions.
+	hacks.addAssetHooks(Common::SharedPtr<AssetHooks>(new ObsidianCorruptedAirTowerTransitionFix()));
+}
+
 void addObsidianImprovedWidescreen(const MTropolisGameDescription &desc, Hacks &hacks) {
 	if ((desc.desc.flags & ADGF_DEMO) == 0 && desc.desc.language == Common::EN_ANY && desc.desc.platform == Common::kPlatformWindows) {
 		const uint32 inventoryItemGUIDs[] = {
diff --git a/engines/mtropolis/hacks.h b/engines/mtropolis/hacks.h
index ffe990a081f..3738bbf0a84 100644
--- a/engines/mtropolis/hacks.h
+++ b/engines/mtropolis/hacks.h
@@ -28,8 +28,9 @@
 
 namespace MTropolis {
 
-class StructuralHooks;
+class AssetHooks;
 class ModifierHooks;
+class StructuralHooks;
 struct MTropolisGameDescription;
 
 struct Hacks {
@@ -38,27 +39,22 @@ struct Hacks {
 
 	void addStructuralHooks(uint32 guid, const Common::SharedPtr<StructuralHooks> &hooks);
 	void addModifierHooks(uint32 guid, const Common::SharedPtr<ModifierHooks> &hooks);
+	void addAssetHooks(const Common::SharedPtr<AssetHooks> &hooks);
 
-	// Workaround for bug in Obsidian:
-	// When opening the journal in the intro, a script checks if cGSt.cfst.binjournal is false and if so,
-	// sets cGSt.cfst.binjournal to true and then sets including setting cJournalConst.aksjournpath to the
-	// main journal scene path.  That scene path is used to resolve the scene to go to after clicking
-	// the "Continue" button on the warning that pops up.
-	//
-	// The problem is that cJournalConst uses a project name that doesn't match the retail data, and
-	// cJournalConst is unloaded if the player leaves the journal.  This causes a progression blocker if
-	// the player leaves the journal without clicking Continue.
 	bool ignoreMismatchedProjectNameInObjectLookups;
 
 	Common::Point reportDisplaySize;	// If X or Y is non-zero, report this as the display size
 	Common::Point mainWindowOffset;		// Coordinate offset of the main window
 
-	Common::HashMap<uint32, Common::SharedPtr<StructuralHooks> > *structuralHooks;
-	Common::HashMap<uint32, Common::SharedPtr<ModifierHooks> > *modifierHooks;
+	Common::HashMap<uint32, Common::SharedPtr<StructuralHooks> > structuralHooks;
+	Common::HashMap<uint32, Common::SharedPtr<ModifierHooks> > modifierHooks;
+
+	Common::Array<Common::SharedPtr<AssetHooks> > assetHooks;
 };
 
 namespace HackSuites {
 
+void addObsidianBugFixes(const MTropolisGameDescription &desc, Hacks &hacks);
 void addObsidianImprovedWidescreen(const MTropolisGameDescription &desc, Hacks &hacks);
 
 } // End of namespace HackSuites
diff --git a/engines/mtropolis/mtropolis.cpp b/engines/mtropolis/mtropolis.cpp
index 32b262694bc..eece730ea73 100644
--- a/engines/mtropolis/mtropolis.cpp
+++ b/engines/mtropolis/mtropolis.cpp
@@ -119,7 +119,7 @@ Common::Error MTropolisEngine::run() {
 		preferredColorDepthMode = kColorDepthMode16Bit;
 		enhancedColorDepthMode = kColorDepthMode32Bit;
 
-		_runtime->getHacks().ignoreMismatchedProjectNameInObjectLookups = true;
+		HackSuites::addObsidianBugFixes(*_gameDescription, _runtime->getHacks());
 
 		if (ConfMan.getBool("mtropolis_mod_obsidian_widescreen")) {
 			_runtime->getHacks().reportDisplaySize = Common::Point(640, 480);
diff --git a/engines/mtropolis/plugin/standard.cpp b/engines/mtropolis/plugin/standard.cpp
index e16b5c1b344..4c65750d8e3 100644
--- a/engines/mtropolis/plugin/standard.cpp
+++ b/engines/mtropolis/plugin/standard.cpp
@@ -19,13 +19,14 @@
  *
  */
 
+#include "common/random.h"
+#include "common/config-manager.h"
+
 #include "audio/mididrv.h"
 #include "audio/midiplayer.h"
 #include "audio/midiparser.h"
 #include "audio/midiparser_smf.h"
 
-#include "common/random.h"
-
 #include "mtropolis/plugin/standard.h"
 #include "mtropolis/plugins.h"
 
@@ -158,7 +159,7 @@ private:
 
 class MultiMidiPlayer : public Audio::MidiPlayer {
 public:
-	MultiMidiPlayer();
+	explicit MultiMidiPlayer(bool useDynamicMidiMixer);
 	~MultiMidiPlayer();
 
 	MidiFilePlayer *createFilePlayer(const Common::SharedPtr<Data::Standard::MidiModifier::EmbeddedFile> &file, bool hasTempoOverride, double tempoOverride, uint8 volume, bool loop, uint16 mutedTracks);
@@ -1151,9 +1152,11 @@ void MidiCombinerDynamic::SourceState::deallocate() {
 MidiCombinerDynamic::OutputChannelState::OutputChannelState() : _sourceID(0), _volumeIsAmbiguous(true), _channelID(0), _hasSource(false), _noteOffCounter(0), _numActiveNotes(0) {
 }
 
-MultiMidiPlayer::MultiMidiPlayer() {
-	//_combiner.reset(new MidiCombinerSimple(this));
-	_combiner.reset(new MidiCombinerDynamic(this));
+MultiMidiPlayer::MultiMidiPlayer(bool dynamicMidiMixer) {
+	if (dynamicMidiMixer)
+		_combiner.reset(new MidiCombinerDynamic(this));
+	else
+		_combiner.reset(new MidiCombinerSimple(this));
 
 	createDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
 
@@ -2751,7 +2754,7 @@ const char *SysInfoModifier::getDefaultName() const {
 StandardPlugInHacks::StandardPlugInHacks() : allowGarbledListModData(false) {
 }
 
-StandardPlugIn::StandardPlugIn()
+StandardPlugIn::StandardPlugIn(bool useDynamicMidi)
 	: _cursorModifierFactory(this)
 	, _sTransCtModifierFactory(this)
 	, _mediaCueModifierFactory(this)
@@ -2759,7 +2762,7 @@ StandardPlugIn::StandardPlugIn()
 	, _midiModifierFactory(this)
 	, _listVarModifierFactory(this)
 	, _sysInfoModifierFactory(this) {
-	_midi.reset(new MultiMidiPlayer());
+	_midi.reset(new MultiMidiPlayer(useDynamicMidi));
 }
 
 StandardPlugIn::~StandardPlugIn() {
@@ -2792,7 +2795,9 @@ MultiMidiPlayer *StandardPlugIn::getMidi() const {
 namespace PlugIns {
 
 Common::SharedPtr<PlugIn> createStandard() {
-	return Common::SharedPtr<PlugIn>(new Standard::StandardPlugIn());
+	const bool useDynamicMidi = ConfMan.getBool("mtropolis_mod_dynamic_midi");
+
+	return Common::SharedPtr<PlugIn>(new Standard::StandardPlugIn(useDynamicMidi));
 }
 
 } // End of namespace MTropolis
diff --git a/engines/mtropolis/plugin/standard.h b/engines/mtropolis/plugin/standard.h
index 4182615ce5d..8c655df95ae 100644
--- a/engines/mtropolis/plugin/standard.h
+++ b/engines/mtropolis/plugin/standard.h
@@ -375,7 +375,7 @@ struct StandardPlugInHacks {
 
 class StandardPlugIn : public MTropolis::PlugIn {
 public:
-	StandardPlugIn();
+	explicit StandardPlugIn(bool useDynamicMidi);
 	~StandardPlugIn();
 
 	void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index aaa8fca432f..ed24538dd49 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -3806,7 +3806,7 @@ bool Runtime::runFrame() {
 			_project.reset(new Project(this));
 			_project->setSelfReference(_project);
 
-			_project->loadFromDescription(*desc);
+			_project->loadFromDescription(*desc, getHacks());
 
 			ensureMainWindowExists();
 
@@ -4473,7 +4473,7 @@ void Runtime::loadScene(const Common::SharedPtr<Structural>& scene) {
 
 	Subsection *subsection = static_cast<Subsection *>(scene->getParent());
 
-	_project->loadSceneFromStream(scene, streamID);
+	_project->loadSceneFromStream(scene, streamID, getHacks());
 	debug(1, "Scene loaded OK, materializing objects...");
 	scene->materializeDescendents(this, subsection->getSceneLoadMaterializeScope());
 	debug(1, "Scene materialized OK");
@@ -5840,7 +5840,7 @@ VThreadState Project::consumeCommand(Runtime *runtime, const Common::SharedPtr<M
 	return Structural::consumeCommand(runtime, msg);
 }
 
-void Project::loadFromDescription(const ProjectDescription& desc) {
+void Project::loadFromDescription(const ProjectDescription &desc, const Hacks &hacks) {
 	_resources = desc.getResources();
 	_cursorGraphics = desc.getCursorGraphics();
 
@@ -5945,12 +5945,12 @@ void Project::loadFromDescription(const ProjectDescription& desc) {
 
 	debug(1, "Loading boot stream");
 
-	loadBootStream(bootStreamIndex);
+	loadBootStream(bootStreamIndex, hacks);
 
 	debug(1, "Boot stream loaded successfully");
 }
 
-void Project::loadSceneFromStream(const Common::SharedPtr<Structural>& scene, uint32 streamID) {
+void Project::loadSceneFromStream(const Common::SharedPtr<Structural> &scene, uint32 streamID, const Hacks &hacks) {
 	if (streamID == 0 || streamID > _streams.size()) {
 		error("Invalid stream ID");
 	}
@@ -6020,7 +6020,7 @@ void Project::loadSceneFromStream(const Common::SharedPtr<Structural>& scene, ui
 	}
 
 	scene->holdAssets(assetDefLoader.assets);
-	assignAssets(assetDefLoader.assets);
+	assignAssets(assetDefLoader.assets, hacks);
 }
 
 Common::SharedPtr<Modifier> Project::resolveAlias(uint32 aliasID) const {
@@ -6161,7 +6161,7 @@ const Common::SharedPtr<CursorGraphicCollection> &Project::getCursorGraphics() c
 	return _cursorGraphics;
 }
 
-void Project::loadBootStream(size_t streamIndex) {
+void Project::loadBootStream(size_t streamIndex, const Hacks &hacks) {
 	const StreamDesc &streamDesc = _streams[streamIndex];
 
 	size_t segmentIndex = streamDesc.segmentIndex;
@@ -6243,7 +6243,7 @@ void Project::loadBootStream(size_t streamIndex) {
 	}
 
 	holdAssets(assetDefLoader.assets);
-	assignAssets(assetDefLoader.assets);
+	assignAssets(assetDefLoader.assets, hacks);
 }
 
 void Project::loadPresentationSettings(const Data::PresentationSettings &presentationSettings) {
@@ -6336,13 +6336,11 @@ Common::SharedPtr<Modifier> Project::loadModifierObject(ModifierLoaderContext &l
 		error("Modifier object failed to load");
 
 	uint32 guid = modifier->getStaticGUID();
-	const Common::HashMap<uint32, Common::SharedPtr<ModifierHooks> > *hooksMap = _runtime->getHacks().modifierHooks;
-	if (hooksMap) {
-		Common::HashMap<uint32, Common::SharedPtr<ModifierHooks> >::const_iterator it = hooksMap->find(guid);
-		if (it != hooksMap->end()) {
-			modifier->setHooks(it->_value);
-			it->_value->onCreate(modifier.get());
-		}
+	const Common::HashMap<uint32, Common::SharedPtr<ModifierHooks> > &hooksMap = _runtime->getHacks().modifierHooks;
+	Common::HashMap<uint32, Common::SharedPtr<ModifierHooks> >::const_iterator hooksIt = hooksMap.find(guid);
+	if (hooksIt != hooksMap.end()) {
+		modifier->setHooks(hooksIt->_value);
+		hooksIt->_value->onCreate(modifier.get());
 	}
 
 	return modifier;
@@ -6414,7 +6412,7 @@ ObjectLinkingScope *Project::getPersistentModifierScope() {
 	return &_modifierScope;
 }
 
-void Project::assignAssets(const Common::Array<Common::SharedPtr<Asset> >& assets) {
+void Project::assignAssets(const Common::Array<Common::SharedPtr<Asset> >& assets, const Hacks &hacks) {
 	for (Common::Array<Common::SharedPtr<Asset> >::const_iterator it = assets.begin(), itEnd = assets.end(); it != itEnd; ++it) {
 		Common::SharedPtr<Asset> asset = *it;
 		uint32 assetID = asset->getAssetID();
@@ -6430,8 +6428,12 @@ void Project::assignAssets(const Common::Array<Common::SharedPtr<Asset> >& asset
 			continue;
 		}
 
-		if (desc->asset.expired())
+		if (desc->asset.expired()) {
 			desc->asset = asset;
+
+			for (const Common::SharedPtr<AssetHooks> &hook : hacks.assetHooks)
+				hook->onLoaded(asset.get(), desc->name);
+		}
 	}
 }
 
@@ -6567,13 +6569,11 @@ void Project::loadContextualObject(size_t streamIndex, ChildLoaderStack &stack,
 				Common::SharedPtr<Element> element = elementFactory->createElement(elementLoaderContext, dataObject);
 
 				uint32 guid = element->getStaticGUID();
-				const Common::HashMap<uint32, Common::SharedPtr<StructuralHooks> > *hooksMap = _runtime->getHacks().structuralHooks;
-				if (hooksMap) {
-					Common::HashMap<uint32, Common::SharedPtr<StructuralHooks> >::const_iterator it = hooksMap->find(guid);
-					if (it != hooksMap->end()) {
-						element->setHooks(it->_value);
-						it->_value->onCreate(element.get());
-					}
+				const Common::HashMap<uint32, Common::SharedPtr<StructuralHooks> > &hooksMap = _runtime->getHacks().structuralHooks;
+				Common::HashMap<uint32, Common::SharedPtr<StructuralHooks> >::const_iterator hooksIt = hooksMap.find(guid);
+				if (hooksIt != hooksMap.end()) {
+					element->setHooks(hooksIt->_value);
+					hooksIt->_value->onCreate(element.get());
 				}
 
 				container->addChild(element);
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 4dbbe467012..8410f2c9be5 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -2129,8 +2129,8 @@ public:
 
 	VThreadState consumeCommand(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg);
 
-	void loadFromDescription(const ProjectDescription &desc);
-	void loadSceneFromStream(const Common::SharedPtr<Structural> &structural, uint32 streamID);
+	void loadFromDescription(const ProjectDescription &desc, const Hacks &hacks);
+	void loadSceneFromStream(const Common::SharedPtr<Structural> &structural, uint32 streamID, const Hacks &hacks);
 
 	Common::SharedPtr<Modifier> resolveAlias(uint32 aliasID) const;
 	void materializeGlobalVariables(Runtime *runtime, ObjectLinkingScope *scope);
@@ -2212,7 +2212,7 @@ private:
 		Common::WeakPtr<Asset> asset;
 	};
 
-	void loadBootStream(size_t streamIndex);
+	void loadBootStream(size_t streamIndex, const Hacks &hacks);
 
 	void loadPresentationSettings(const Data::PresentationSettings &presentationSettings);
 	void loadAssetCatalog(const Data::AssetCatalog &assetCatalog);
@@ -2226,7 +2226,7 @@ private:
 	ObjectLinkingScope *getPersistentStructuralScope() override;
 	ObjectLinkingScope *getPersistentModifierScope() override;
 
-	void assignAssets(const Common::Array<Common::SharedPtr<Asset> > &assets);
+	void assignAssets(const Common::Array<Common::SharedPtr<Asset> > &assets, const Hacks &hacks);
 
 	Common::Array<Segment> _segments;
 	Common::Array<StreamDesc> _streams;
@@ -2660,6 +2660,13 @@ enum AssetType {
 	kAssetTypeMToon,
 };
 
+class AssetHooks {
+public:
+	virtual ~AssetHooks();
+
+	virtual void onLoaded(Asset *asset, const Common::String &name);
+};
+
 class Asset {
 public:
 	Asset();




More information about the Scummvm-git-logs mailing list