[Scummvm-git-logs] scummvm master -> 695b7f92296a48cd695614001dc6391577377101

sluicebox noreply at scummvm.org
Fri Mar 4 03:48:50 UTC 2022


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:
bf72668377 SCI: Handle saving from GMM for LSL3/SQ3 German Amiga
0d12e0add6 SCI: Fix crash on GMM if User object can't be found
e1c749adc6 SCI: Update SQ1VGA script patch notes
695b7f9229 SCI32: Improve SCI3 object parsing


Commit: bf72668377a4c27f3f40f231df34aba007048e10
    https://github.com/scummvm/scummvm/commit/bf72668377a4c27f3f40f231df34aba007048e10
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-03-03T21:54:27-05:00

Commit Message:
SCI: Handle saving from GMM for LSL3/SQ3 German Amiga

Changed paths:
    engines/sci/engine/guest_additions.cpp


diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp
index 3d3338e36a8..8926f567fbb 100644
--- a/engines/sci/engine/guest_additions.cpp
+++ b/engines/sci/engine/guest_additions.cpp
@@ -157,6 +157,12 @@ static Common::String getUserObject(SciGameId gameId) {
 		return "oUser";
 	case GID_PHANTASMAGORIA2:
 		return "p2User";
+	case GID_LSL3:
+	case GID_SQ3:
+		// German Amiga versions
+		if (getSciVersion() == SCI_VERSION_1_MIDDLE)
+			return "PUser";
+		// fallthrough intended
 	default:
 		return "User";
 	}


Commit: 0d12e0add626b53c8e6cf7321e0738462ed76567
    https://github.com/scummvm/scummvm/commit/0d12e0add626b53c8e6cf7321e0738462ed76567
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-03-03T22:26:09-05:00

Commit Message:
SCI: Fix crash on GMM if User object can't be found

Changed paths:
    engines/sci/engine/guest_additions.cpp


diff --git a/engines/sci/engine/guest_additions.cpp b/engines/sci/engine/guest_additions.cpp
index 8926f567fbb..8fb0c0e0049 100644
--- a/engines/sci/engine/guest_additions.cpp
+++ b/engines/sci/engine/guest_additions.cpp
@@ -172,6 +172,12 @@ bool GuestAdditions::userHasControl() {
 	const SciGameId gameId = g_sci->getGameId();
 	const reg_t user = _segMan->findObjectByName(getUserObject(gameId));
 	const Object *userObject = _segMan->getObject(user);
+	if (userObject == nullptr) {
+		// Several Mac games like QFG1VGA don't contain object names, and some
+		// third party localizations like SQ1VGA Russian altered object names.
+		warning("User object not found");
+		return false;
+	}
 
 	// Selectors input/canInput and controls should be available at all times, except
 	// in games that don't have selector vocab 997 (e.g. some game demos and LB2 floppy)


Commit: e1c749adc6576c9cc11809d11e8c513f157870e5
    https://github.com/scummvm/scummvm/commit/e1c749adc6576c9cc11809d11e8c513f157870e5
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-03-03T22:26:09-05:00

Commit Message:
SCI: Update SQ1VGA script patch notes

Changed paths:
    engines/sci/engine/script_patches.cpp


diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 39e70f1ec47..52058498024 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -20156,16 +20156,24 @@ static const uint16 sq1vgaPatchUlenceFlatsTimepodGfxGlitch[] = {
 	PATCH_END
 };
 
-// In Ulence Flats, there is a space ship, that you will use at some point.
+// In Ulence Flats, there is a space ship that you will use in room 45.
 //  Near that space ship are 2 force field generators. When you look at the top
 //  of those generators, the game will crash. This happens also in Sierra SCI.
-//  It's caused by a jump, that goes out of bounds.
+//  It's caused by a branch that goes out of bounds.
 //
-// We currently do not know if this was caused by a compiler glitch or if it
-//  was a developer error. Anyway we patch this glitchy code, so that the game
-//  won't crash anymore.
+// This was due to a compiler bug that produced bogus bnt targets when the body
+//  of the last switch or cond condition was empty. These appear in other games
+//  but in each case the final condition always evaluated to true, or was never
+//  reached, and so the bug went unnoticed. In this case it appears that the
+//  intended body of the else statement was a call to super:doVerb but instead
+//  it was entered as the final condition. This created an empty body and a
+//  condition which happened to evaluate to zero, and so a bogus branch was
+//  finally taken and crashed. The script was fixed in later versions and the
+//  compiler was fixed to no longer emit these broken bnt instructions.
 //
-// Applies to at least: English Floppy
+// We fix this by patching out the bogus branch instruction.
+//
+// Applies to: English PC VGA
 // Responsible method: radar1::doVerb
 // Fixes bug: #6816
 static const uint16 sq1vgaSignatureUlenceFlatsGeneratorGlitch[] = {


Commit: 695b7f92296a48cd695614001dc6391577377101
    https://github.com/scummvm/scummvm/commit/695b7f92296a48cd695614001dc6391577377101
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2022-03-03T22:26:09-05:00

Commit Message:
SCI32: Improve SCI3 object parsing

Adjust the parsing code to more accurately reflect the
resource format. Adds more comments and less allocations.

Changed paths:
    engines/sci/engine/object.cpp


diff --git a/engines/sci/engine/object.cpp b/engines/sci/engine/object.cpp
index 4d7f23d24bd..2fdbb9118f0 100644
--- a/engines/sci/engine/object.cpp
+++ b/engines/sci/engine/object.cpp
@@ -379,15 +379,23 @@ bool Object::mustSetViewVisible(int index, const bool fromPropertyOp) const {
 
 void Object::initSelectorsSci3(const SciSpan<const byte> &buf, const bool initVariables) {
 	enum {
-		kExtraGroups = 3,
-		kGroupSize   = 32
+		kObjectHeaderSize = 16,
+		kSelectorBankSize = 256,
+		kGroupSize = 64,
+		kSelectorsInGroup = 32
 	};
 
-	const SciSpan<const byte> groupInfo = _baseObj.subspan(16);
-	const SciSpan<const byte> selectorBase = groupInfo.subspan(kExtraGroups * kGroupSize * sizeof(uint16));
-
-	int numGroups = g_sci->getKernel()->getSelectorNamesSize() / kGroupSize;
-	if (g_sci->getKernel()->getSelectorNamesSize() % kGroupSize)
+	// The selector bank is a 256 byte array. Each byte represents a range of
+	// 32 selectors. If an object has any selectors in the range then this
+	// byte is a one-based index to the list of selector-group structures that
+	// follows, otherwise it is zero.
+	const SciSpan<const byte> selectorBank = _baseObj.subspan(kObjectHeaderSize, kSelectorBankSize);
+	const SciSpan<const byte> groups = _baseObj.subspan(kObjectHeaderSize + kSelectorBankSize);
+	
+	// Instead of testing all 256 selector bank entries, we calculate how many
+	// groups there are according to the size of the selector table.
+	int numGroups = g_sci->getKernel()->getSelectorNamesSize() / kSelectorsInGroup;
+	if (g_sci->getKernel()->getSelectorNamesSize() % kSelectorsInGroup)
 		++numGroups;
 
 	_mustSetViewVisible.resize(numGroups);
@@ -395,23 +403,24 @@ void Object::initSelectorsSci3(const SciSpan<const byte> &buf, const bool initVa
 	int numMethods = 0;
 	int numProperties = 0;
 
-	// Selectors are divided into groups of 32, of which the first
-	// two selectors are always reserved (because their storage
-	// space is used by the typeMask).
+	// Selectors are divided into groups of 32, of which the first two selectors
+	// are unused because their bytes are used for a 32-bit typeMask that indicates
+	// which of the remaining 30 selectors are properties. This means that in SCI3
+	// there are no selectors with the values 0, 1, 32, 33, etc.
 	// We don't know beforehand how many methods and properties
 	// there are, so we count them first.
-	for (int groupNr = 0; groupNr < numGroups; ++groupNr) {
-		byte groupLocation = groupInfo[groupNr];
-		const SciSpan<const byte> seeker = selectorBase.subspan(groupLocation * kGroupSize * sizeof(uint16));
+	for (int bankIndex = 0; bankIndex < numGroups; ++bankIndex) {
+		byte groupIndex = selectorBank[bankIndex]; // one-based index
 
-		if (groupLocation != 0)	{
+		if (groupIndex != 0)	{
 			// This object actually has selectors belonging to this group
-			int typeMask = seeker.getUint32SEAt(0);
+			const SciSpan<const byte> group = groups.subspan((groupIndex - 1) * kGroupSize, kGroupSize);
+			uint32 typeMask = group.getUint32SEAt(0);
 
-			_mustSetViewVisible[groupNr] = (typeMask & 1);
+			_mustSetViewVisible[bankIndex] = (typeMask & 1);
 
-			for (int bit = 2; bit < kGroupSize; ++bit) {
-				int value = seeker.getUint16SEAt(bit * sizeof(uint16));
+			for (int bit = 2; bit < kSelectorsInGroup; ++bit) {
+				uint16 value = group.getUint16SEAt(bit * sizeof(uint16));
 				if (typeMask & (1 << bit)) { // Property
 					++numProperties;
 				} else if (value != 0xffff) { // Method
@@ -421,10 +430,11 @@ void Object::initSelectorsSci3(const SciSpan<const byte> &buf, const bool initVa
 				}
 			}
 		} else
-			_mustSetViewVisible[groupNr] = false;
+			_mustSetViewVisible[bankIndex] = false;
 	}
 
 	_methodCount = numMethods;
+	_baseMethod.resize(numMethods * 2);
 	_variables.resize(numProperties);
 	_baseVars.resize(numProperties);
 	_propertyOffsetsSci3.resize(numProperties);
@@ -432,30 +442,33 @@ void Object::initSelectorsSci3(const SciSpan<const byte> &buf, const bool initVa
 	// Go through the whole thing again to get the property values
 	// and method pointers
 	int propertyCounter = 0;
-	for (int groupNr = 0; groupNr < numGroups; ++groupNr) {
-		byte groupLocation = groupInfo[groupNr];
-		const SciSpan<const byte> seeker = selectorBase.subspan(groupLocation * kGroupSize * sizeof(uint16));
+	int methodCounter = 0;
+	uint32 codeOffset = buf.getUint32SEAt(0);
+	for (int bankIndex = 0; bankIndex < numGroups; ++bankIndex) {
+		byte groupIndex = selectorBank[bankIndex]; // one-based index
 
-		if (groupLocation != 0)	{
+		if (groupIndex != 0)	{
 			// This object actually has selectors belonging to this group
-			int typeMask = seeker.getUint32SEAt(0);
-			int groupBaseId = groupNr * kGroupSize;
+			const SciSpan<const byte> group = groups.subspan((groupIndex - 1) * kGroupSize, kGroupSize);
+			uint32 typeMask = group.getUint32SEAt(0);
+			int groupBaseId = bankIndex * kSelectorsInGroup;
 
-			for (int bit = 2; bit < kGroupSize; ++bit) {
-				int value = seeker.getUint16SEAt(bit * sizeof(uint16));
+			for (int bit = 2; bit < kSelectorsInGroup; ++bit) {
+				uint16 value = group.getUint16SEAt(bit * sizeof(uint16));
 				if (typeMask & (1 << bit)) { // Property
 					_baseVars[propertyCounter] = groupBaseId + bit;
 					if (initVariables) {
 						_variables[propertyCounter] = make_reg(0, value);
 					}
-					uint32 propertyOffset = (seeker + bit * sizeof(uint16)) - buf;
+					uint32 propertyOffset = (group + bit * sizeof(uint16)) - buf;
 					_propertyOffsetsSci3[propertyCounter] = propertyOffset;
 					++propertyCounter;
 				} else if (value != 0xffff) { // Method
-					_baseMethod.push_back(groupBaseId + bit);
-					const uint32 offset = value + buf.getUint32SEAt(0);
-					assert(offset <= kOffsetMask);
-					_baseMethod.push_back(offset);
+					_baseMethod[methodCounter * 2] = groupBaseId + bit;
+					uint32 methodOffset = value + codeOffset;
+					assert(methodOffset <= kOffsetMask);
+					_baseMethod[methodCounter * 2 + 1] = methodOffset;
+					++methodCounter;
 				} else {
 					// Undefined selector
 				}




More information about the Scummvm-git-logs mailing list