aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsluicebox2019-07-07 19:18:04 -0700
committerFilippos Karapetis2019-07-09 09:51:10 +0300
commitca66a776b0444a4af5cde844a924b8f25baffb77 (patch)
tree6c4773fbeaefd85be715982ce5af7d707f2a0973
parent14fe8ac3a0243fe356a604127e60c6104dd66cc4 (diff)
downloadscummvm-rg350-ca66a776b0444a4af5cde844a924b8f25baffb77.tar.gz
scummvm-rg350-ca66a776b0444a4af5cde844a924b8f25baffb77.tar.bz2
scummvm-rg350-ca66a776b0444a4af5cde844a924b8f25baffb77.zip
SCI: Implement early GetLongest() behavior, bug #10000
-rw-r--r--engines/sci/engine/features.cpp50
-rw-r--r--engines/sci/engine/features.h2
-rw-r--r--engines/sci/graphics/text16.cpp20
-rw-r--r--engines/sci/graphics/text16.h2
4 files changed, 73 insertions, 1 deletions
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 5d01aea32f..980e417d7e 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -774,4 +774,54 @@ PseudoMouseAbilityType GameFeatures::detectPseudoMouseAbility() {
return _pseudoMouseAbility;
}
+// GetLongest(), which calculates the number of characters in a string that can fit
+// within a width, had two subtle changes which started to appear in interpreters
+// in late 1990. An off-by-one bug was fixed where the character that exceeds the
+// width would be applied to the result if a space character hadn't been reached.
+// The pixel width test was also changed from a greater than or equals to greater
+// than, but again only if a space character hadn't been reached.
+//
+// The notebook in LB1 (bug #10000) is currently the only known script that depended
+// on the original behavior. This appears to be an isolated fix to an interpreter
+// edge case, a corresponding script change to allow autodetection hasn't been found.
+//
+// The Japanese interpreters have their own versions of GetLongest() to support
+// double byte characters which seems to be how QFG1 Japanese reintroduced it
+// even though its interpreter is later than SQ3/LSL3 multilingual versions.
+bool GameFeatures::useEarlyGetLongestTextCalculations() const {
+ switch (getSciVersion()) {
+
+ // All SCI0, confirmed:
+ // - LSL2 English PC 1.000.011
+ // - LB1 PC 1.000.046
+ // - ICEMAN PC 1.033
+ // - SQ3 English PC 1.018
+ // - PQ2 Japanese 1.000.052
+ case SCI_VERSION_0_EARLY:
+ case SCI_VERSION_0_LATE:
+ return true;
+
+ // SCI01: confirmed KQ1 and QFG1 Japanese,
+ // fixed in SQ3 and LSL3 multilingual PC
+ case SCI_VERSION_01:
+ return (g_sci->getGameId() == GID_KQ1 || g_sci->getGameId() == GID_QFG1);
+
+ // QFG2, confirmed 1.000 and 1.105 (first and last versions)
+ case SCI_VERSION_1_EGA_ONLY:
+ return true;
+
+ // SCI1 Early: just KQ5 English PC versions,
+ // confirmed fixed in:
+ // - LSL1 Demo
+ // - XMAS1990 EGA
+ // - SQ4 1.052
+ case SCI_VERSION_1_EARLY:
+ return (g_sci->getGameId() == GID_KQ5);
+
+ // Fixed in all other versions
+ default:
+ return false;
+ }
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h
index 42d710f9a6..01535ce3dc 100644
--- a/engines/sci/engine/features.h
+++ b/engines/sci/engine/features.h
@@ -245,6 +245,8 @@ public:
*/
PseudoMouseAbilityType detectPseudoMouseAbility();
+ bool useEarlyGetLongestTextCalculations() const;
+
private:
reg_t getDetectionAddr(const Common::String &objName, Selector slc, int methodNum = -1);
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index a661de63f9..cdb7c260d4 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -25,6 +25,7 @@
#include "graphics/primitives.h"
#include "sci/sci.h"
+#include "sci/engine/features.h"
#include "sci/engine/state.h"
#include "sci/graphics/cache.h"
#include "sci/graphics/coordadjuster.h"
@@ -50,6 +51,7 @@ void GfxText16::init() {
_codeFontsCount = 0;
_codeColors = NULL;
_codeColorsCount = 0;
+ _useEarlyGetLongestTextCalculations = g_sci->_features->useEarlyGetLongestTextCalculations();
}
GuiResourceId GfxText16::GetFontId() {
@@ -250,6 +252,14 @@ int16 GfxText16::GetLongest(const char *&textPtr, int16 maxWidth, GuiResourceId
if (tempWidth > maxWidth)
break;
+ // the previous greater than test was originally a greater than or equals when
+ // no space character had been reached yet
+ if (_useEarlyGetLongestTextCalculations) {
+ if (lastSpaceCharCount == 0 && tempWidth == maxWidth) {
+ break;
+ }
+ }
+
// still fits, remember width
curWidth = tempWidth;
@@ -273,7 +283,7 @@ int16 GfxText16::GetLongest(const char *&textPtr, int16 maxWidth, GuiResourceId
} else {
// Break without spaces found, we split the very first word - may also be Kanji/Japanese
if (curChar > 0xFF) {
- // current charracter is Japanese
+ // current character is Japanese
// PC-9801 SCI actually added the last character, which shouldn't fit anymore, still onto the
// screen in case maxWidth wasn't fully reached with the last character
@@ -330,6 +340,14 @@ int16 GfxText16::GetLongest(const char *&textPtr, int16 maxWidth, GuiResourceId
// (game mentions Mixed Up Fairy Tales and uses English letters for that)
textPtr += 2;
}
+ } else {
+ // Add a character to the count for games whose interpreter would count the
+ // character that exceeded the width if a space hadn't been reached yet.
+ // Fixes #10000 where the notebook in LB1 room 786 displays "INCOMPLETE" with
+ // a width that's too short which would have otherwise wrapped the last "E".
+ if (_useEarlyGetLongestTextCalculations) {
+ curCharCount++; textPtr++;
+ }
}
// We split the word in that case
diff --git a/engines/sci/graphics/text16.h b/engines/sci/graphics/text16.h
index cb3deb0c60..32d5481dcc 100644
--- a/engines/sci/graphics/text16.h
+++ b/engines/sci/graphics/text16.h
@@ -90,6 +90,8 @@ private:
int _codeColorsCount;
uint16 *_codeColors;
+ bool _useEarlyGetLongestTextCalculations;
+
Common::Rect _codeRefTempRect;
CodeRefRectArray _codeRefRects;
};