[Scummvm-git-logs] scummvm master -> 8eb323644ddb07628e432cc8be4db2584aa771ff

elasota noreply at scummvm.org
Fri Jul 5 02:14:25 UTC 2024


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

Summary:
299b98089b MTROPOLIS: Improve vthread stack debug
dbc4579e3b MTROPOLIS: Fix media cue modifier not cloning correctly
d13568b185 MTROPOLIS: Sink invalid attrib writes that are documented as allowed in 1.x
8eb323644d MTROPOLIS: Resolve str2num failures to 0 and warn instead


Commit: 299b98089bcdf89e4c831b996cafda0803b76c83
    https://github.com/scummvm/scummvm/commit/299b98089bcdf89e4c831b996cafda0803b76c83
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-07-04T20:39:53-04:00

Commit Message:
MTROPOLIS: Improve vthread stack debug

Changed paths:
    engines/mtropolis/vthread.cpp
    engines/mtropolis/vthread.h


diff --git a/engines/mtropolis/vthread.cpp b/engines/mtropolis/vthread.cpp
index 517cb5f47b7..14cf5ba18c7 100644
--- a/engines/mtropolis/vthread.cpp
+++ b/engines/mtropolis/vthread.cpp
@@ -38,7 +38,12 @@ void VThreadTaskData::debugInspect(IDebugInspectionReport *report) const {
 }
 #endif
 
-VThread::VThread() : _faultID(nullptr), _stackUnalignedBase(nullptr), _stackAlignedBase(nullptr), /* _size(0), */_alignment(1), _used(0) {
+VThread::VThread()
+	: _faultID(nullptr), _stackUnalignedBase(nullptr), _stackAlignedBase(nullptr), /* _size(0), */_alignment(1), _used(0)
+#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
+	, _topFrame(nullptr)
+#endif
+{
 }
 
 VThread::~VThread() {
@@ -59,8 +64,10 @@ VThreadState VThread::step() {
 	while (popFrame(dataPtr, framePtr)) {
 		VThreadTaskData *data = static_cast<VThreadTaskData *>(dataPtr);
 
+		VThreadStackFrame *stackFrame = static_cast<VThreadStackFrame *>(framePtr);
+
 		const bool isHandling = (data->handlesFault(_faultID));
-		static_cast<VThreadStackFrame *>(framePtr)->~VThreadStackFrame();
+		stackFrame->~VThreadStackFrame();
 		if (isHandling) {
 			_faultID = nullptr;
 			VThreadState state = data->destructAndRunTask();
@@ -175,6 +182,10 @@ void VThread::reserveFrame(size_t size, size_t alignment, void *&outFramePtr, vo
 	outFramePtr = newFrame;
 	outUnadjustedDataPtr = newData;
 	outPrevFrameOffset = offsetOfPrevFrame;
+
+#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
+	_topFrame = newFrame;
+#endif
 }
 
 bool VThread::popFrame(void *&dataPtr, void *&outFramePtr) {
@@ -192,6 +203,13 @@ bool VThread::popFrame(void *&dataPtr, void *&outFramePtr) {
 	else
 		_used = frame->prevFrameOffset + sizeof(VThreadStackFrame);
 
+#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
+	if (_used == 0)
+		_topFrame = nullptr;
+	else
+		_topFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + frame->prevFrameOffset);
+#endif
+
 	return true;
 }
 
diff --git a/engines/mtropolis/vthread.h b/engines/mtropolis/vthread.h
index b9a536c677f..96518fb3eea 100644
--- a/engines/mtropolis/vthread.h
+++ b/engines/mtropolis/vthread.h
@@ -156,6 +156,10 @@ private:
 	size_t _alignment;
 	size_t _used;
 	VThreadFaultIdentifier *_faultID;
+
+#ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
+	const VThreadStackFrame *_topFrame;
+#endif
 };
 
 template<typename TClass, typename TData>
@@ -286,7 +290,11 @@ TData *VThread::pushTaskWithFaultHandler(const VThreadFaultIdentifier *faultID,
 	frame->taskDataOffset = reinterpret_cast<char *>(static_cast<VThreadTaskData *>(frameData)) - static_cast<char *>(_stackAlignedBase);
 
 #ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-	frame->prevFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + prevFrameOffset);
+	if (frame->prevFrameOffset == 0)
+		frame->prevFrame = nullptr;
+	else
+		frame->prevFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + prevFrameOffset);
+
 	frame->data = frameData;
 #endif
 #ifdef MTROPOLIS_DEBUG_ENABLE
@@ -316,7 +324,11 @@ TData *VThread::pushTaskWithFaultHandler(const VThreadFaultIdentifier *faultID,
 	frame->taskDataOffset = reinterpret_cast<char *>(static_cast<VThreadTaskData *>(frameData)) - static_cast<char *>(_stackAlignedBase);
 
 #ifdef MTROPOLIS_DEBUG_VTHREAD_STACKS
-	frame->prevFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + prevFrameOffset);
+	if (frame->prevFrameOffset == 0)
+		frame->prevFrame = nullptr;
+	else
+		frame->prevFrame = reinterpret_cast<VThreadStackFrame *>(static_cast<char *>(_stackAlignedBase) + prevFrameOffset);
+
 	frame->data = frameData;
 #endif
 #ifdef MTROPOLIS_DEBUG_ENABLE


Commit: dbc4579e3b4429c7d554c01df10c8bb5a971d8cf
    https://github.com/scummvm/scummvm/commit/dbc4579e3b4429c7d554c01df10c8bb5a971d8cf
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-07-04T21:37:08-04:00

Commit Message:
MTROPOLIS: Fix media cue modifier not cloning correctly

Fixes crash in the Bureau maze in Obsidian

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


diff --git a/engines/mtropolis/plugin/standard.cpp b/engines/mtropolis/plugin/standard.cpp
index 5b4c620bb33..abe6f300f9c 100644
--- a/engines/mtropolis/plugin/standard.cpp
+++ b/engines/mtropolis/plugin/standard.cpp
@@ -237,7 +237,7 @@ MediaCueMessengerModifier::MediaCueMessengerModifier() : _isActive(false), _cueS
 }
 
 MediaCueMessengerModifier::MediaCueMessengerModifier(const MediaCueMessengerModifier &other)
-	: _cueSourceType(other._cueSourceType), _cueSourceModifier(other._cueSourceModifier), _enableWhen(other._enableWhen), _disableWhen(other._disableWhen), _mediaCue(other._mediaCue), _isActive(other._isActive) {
+	: Modifier(other), _cueSourceType(other._cueSourceType), _cueSourceModifier(other._cueSourceModifier), _enableWhen(other._enableWhen), _disableWhen(other._disableWhen), _mediaCue(other._mediaCue), _isActive(other._isActive) {
 	_cueSource.destruct<uint64, &CueSourceUnion::asUnset>();
 
 	switch (_cueSourceType) {


Commit: d13568b1858b6b2d1ce38236dbe6b9be909dfeef
    https://github.com/scummvm/scummvm/commit/d13568b1858b6b2d1ce38236dbe6b9be909dfeef
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-07-04T21:40:35-04:00

Commit Message:
MTROPOLIS: Sink invalid attrib writes that are documented as allowed in 1.x

Changed paths:
    engines/mtropolis/elements.cpp
    engines/mtropolis/runtime.cpp
    engines/mtropolis/runtime.h


diff --git a/engines/mtropolis/elements.cpp b/engines/mtropolis/elements.cpp
index 5b2cecfdce7..488b6b3de83 100644
--- a/engines/mtropolis/elements.cpp
+++ b/engines/mtropolis/elements.cpp
@@ -1382,7 +1382,7 @@ VThreadState MToonElement::consumeCommand(Runtime *runtime, const Common::Shared
 		// mTropolis 1.0 will not fire a Hidden event when an mToon is stopped even though it is hidden in the process.
 		// MTI depends on this, otherwise 2 hints will play at once when clicking a song button on the piano.
 		// This same bug does NOT apply to the "Shown" event firing on Play (as happens above).
-		if (runtime->getProject()->guessVersion() >= MTropolisVersions::kMTropolisVersion1_1) {
+		if (runtime->getProject()->getRuntimeVersion() > kRuntimeVersion100) {
 			ChangeFlagTaskData *hideTaskData = runtime->getVThread().pushTask("MToonElement::changeVisibilityTask", static_cast<VisualElement *>(this), &MToonElement::changeVisibilityTask);
 			hideTaskData->desiredFlag = false;
 			hideTaskData->runtime = runtime;
diff --git a/engines/mtropolis/runtime.cpp b/engines/mtropolis/runtime.cpp
index 159b58c60ae..d4bec6ea2f5 100644
--- a/engines/mtropolis/runtime.cpp
+++ b/engines/mtropolis/runtime.cpp
@@ -2708,6 +2708,27 @@ bool RuntimeObject::readAttributeIndexed(MiniscriptThread *thread, DynamicValue
 }
 
 MiniscriptInstructionOutcome RuntimeObject::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) {
+	if (thread->getRuntime()->getProject()->getRuntimeVersion() < kRuntimeVersion200) {
+		// Per 2.0 release notes, the following attrib writes succeed without error
+		// on all objects
+		const char *sunkAttribs[] = {
+			"position", "width", "height", "rate", "range", "cel", "text", "volume", "timevalue",
+			"mastervolume", "usertimeout", "layer", "paused", "trackenable", "trackdisable",
+			"cache", "direct", "loop", "visible", "loopbackforth", "playeveryframe"
+		};
+
+		for (const char *sunkAttrib : sunkAttribs) {
+			if (attrib == sunkAttrib) {
+#ifdef MTROPOLIS_DEBUG_ENABLE
+				if (Debugger *debugger = thread->getRuntime()->debugGetDebugger())
+					debugger->notify(kDebugSeverityWarning, Common::String::format("'%s' attribute write was discarded", sunkAttrib));
+#endif
+				DynamicValueWriteDiscardHelper::create(writeProxy);
+				return kMiniscriptInstructionOutcomeContinue;
+			}
+		}
+	}
+
 	return kMiniscriptInstructionOutcomeFailed;
 }
 
@@ -7049,7 +7070,7 @@ Project::AssetDesc::AssetDesc() : typeCode(0), id(0), streamID(0), filePosition(
 Project::Project(Runtime *runtime)
 	: Structural(runtime), _projectFormat(Data::kProjectFormatUnknown),
 	  _haveGlobalObjectInfo(false), _haveProjectStructuralDef(false), _playMediaSignaller(new PlayMediaSignaller()),
-	  _keyboardEventSignaller(new KeyboardEventSignaller()), _guessedVersion(MTropolisVersions::kMTropolisVersion1_0),
+	  _keyboardEventSignaller(new KeyboardEventSignaller()),
 	  _platform(kProjectPlatformUnknown), _rootArchive(nullptr), _runtimeVersion(kRuntimeVersion100) {
 }
 
@@ -7643,8 +7664,8 @@ const SubtitleTables &Project::getSubtitles() const {
 	return _subtitles;
 }
 
-MTropolisVersions::MTropolisVersion Project::guessVersion() const {
-	return _guessedVersion;
+RuntimeVersion Project::getRuntimeVersion() const {
+	return _runtimeVersion;
 }
 
 ProjectPlatform Project::getPlatform() const {
@@ -7701,14 +7722,6 @@ void Project::loadAssetCatalog(const Data::AssetCatalog &assetCatalog) {
 				_assetNameToID[assetDesc.name] = assetDesc.id;
 		}
 	}
-
-	if (assetCatalog.getRevision() <= 2)
-		_guessedVersion = MTropolisVersions::kMTropolisVersion1_0;
-	else if (assetCatalog.getRevision() <= 4)
-		_guessedVersion = MTropolisVersions::kMTropolisVersion1_1;
-	else
-		_guessedVersion = MTropolisVersions::kMTropolisVersion2_0;
-
 }
 
 void Project::loadGlobalObjectInfo(ChildLoaderStack &loaderStack, const Data::GlobalObjectInfo& globalObjectInfo) {
diff --git a/engines/mtropolis/runtime.h b/engines/mtropolis/runtime.h
index 5be43e14ee1..d66e251f3a1 100644
--- a/engines/mtropolis/runtime.h
+++ b/engines/mtropolis/runtime.h
@@ -328,16 +328,6 @@ bool isCommand(EventID eventID);
 
 } // End of namespace EventIDs
 
-namespace MTropolisVersions {
-
-enum MTropolisVersion {
-	kMTropolisVersion1_0,
-	kMTropolisVersion1_1,
-	kMTropolisVersion2_0,
-};
-
-} // End of namespace MTropolisVersions
-
 MiniscriptInstructionOutcome pointWriteRefAttrib(Common::Point &point, MiniscriptThread *thread, DynamicValueWriteProxy &proxy, const Common::String &attrib);
 Common::String pointToString(const Common::Point &point);
 
@@ -2455,7 +2445,7 @@ public:
 
 	const SubtitleTables &getSubtitles() const;
 
-	MTropolisVersions::MTropolisVersion guessVersion() const;
+	RuntimeVersion getRuntimeVersion() const;
 	ProjectPlatform getPlatform() const;
 
 #ifdef MTROPOLIS_DEBUG_ENABLE
@@ -2573,7 +2563,6 @@ private:
 
 	SubtitleTables _subtitles;
 
-	MTropolisVersions::MTropolisVersion _guessedVersion;
 	ProjectPlatform _platform;
 
 	Common::Archive *_rootArchive;


Commit: 8eb323644ddb07628e432cc8be4db2584aa771ff
    https://github.com/scummvm/scummvm/commit/8eb323644ddb07628e432cc8be4db2584aa771ff
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-07-04T22:14:01-04:00

Commit Message:
MTROPOLIS: Resolve str2num failures to 0 and warn instead

Changed paths:
    engines/mtropolis/miniscript.cpp


diff --git a/engines/mtropolis/miniscript.cpp b/engines/mtropolis/miniscript.cpp
index b18122a0a18..313a969883f 100644
--- a/engines/mtropolis/miniscript.cpp
+++ b/engines/mtropolis/miniscript.cpp
@@ -1248,9 +1248,21 @@ MiniscriptInstructionOutcome BuiltinFunc::executeStr2Num(MiniscriptThread *threa
 	const Common::String &str = inputDynamicValue.getString();
 	if (str.empty())
 		result = 0.0;
-	else if (str.size() == 0 || !sscanf(str.c_str(), "%lf", &result)) {
-		thread->error("Couldn't parse number");
-		return kMiniscriptInstructionOutcomeFailed;
+	else if (!sscanf(str.c_str(), "%lf", &result)) {
+		// NOTE: sscanf will properly handle cases where a number is followed by a non-numeric value,
+		// which is consistent with mTropolis' behavior.
+		// 
+		// If it fails, the result is 0.0 and no script error.
+		//
+		// This includes a case in Obsidian where it tries to parse in invalid room number "L100"
+		// upon entering the sky face for the first time in Bureau.
+
+#ifdef MTROPOLIS_DEBUG_ENABLE
+		if (Debugger *debugger = thread->getRuntime()->debugGetDebugger())
+			debugger->notify(kDebugSeverityError, Common::String::format("Failed to parse '%s' as a number", str.c_str()));
+#endif
+
+		result = 0.0;
 	}
 
 	returnValue->setFloat(result);




More information about the Scummvm-git-logs mailing list