[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