aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/features.cpp6
-rw-r--r--engines/sci/engine/kernel.h4
-rw-r--r--engines/sci/engine/kernel_tables.h3
-rw-r--r--engines/sci/engine/kfile.cpp20
-rw-r--r--engines/sci/engine/kgraphics.cpp33
-rw-r--r--engines/sci/engine/kstring.cpp10
-rw-r--r--engines/sci/engine/savegame.cpp10
-rw-r--r--engines/sci/engine/script_patches.cpp61
-rw-r--r--engines/sci/engine/script_patches.h2
-rw-r--r--engines/sci/engine/seg_manager.cpp2
-rw-r--r--engines/sci/engine/state.cpp115
-rw-r--r--engines/sci/engine/workarounds.cpp6
12 files changed, 208 insertions, 64 deletions
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 31e7ca4931..be062dba64 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -344,9 +344,9 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) {
if (kFuncNum == 8) { // kDrawPic (SCI0 - SCI11)
// If kDrawPic is called with 6 parameters from the overlay
// selector, the game is using old graphics functions.
- // Otherwise, if it's called with 8 parameters, it's using new
- // graphics functions.
- _gfxFunctionsType = (argc == 8) ? SCI_VERSION_0_LATE : SCI_VERSION_0_EARLY;
+ // Otherwise, if it's called with 8 parameters (e.g. SQ3) or 4 parameters
+ // (e.g. Hoyle 1/2), it's using new graphics functions.
+ _gfxFunctionsType = (argc == 6) ? SCI_VERSION_0_EARLY : SCI_VERSION_0_LATE;
return true;
}
}
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index dddf845222..a65bcb7df5 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -145,7 +145,7 @@ public:
*/
Kernel(ResourceManager *resMan, SegManager *segMan);
~Kernel();
-
+
void init();
uint getSelectorNamesSize() const;
@@ -161,7 +161,7 @@ public:
* @return The appropriate selector ID, or -1 on error
*/
int findSelector(const char *selectorName) const;
-
+
bool selectorNamesAvailable();
// Script dissection/dumping functions
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index fc46d16b8d..0c2fd4e3ea 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -468,7 +468,8 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL },
{ "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL },
- { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, kUnLoad_workarounds },
+ { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ir!]", NULL, kUnLoad_workarounds },
+ // ^ We allow invalid references here (e.g. bug #6600), since they will be invalidated anyway by the call itself
{ MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL },
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 61fb717567..c56eb09482 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -37,6 +37,7 @@
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/engine/savegame.h"
+#include "sci/graphics/menu.h"
#include "sci/sound/audio.h"
#include "sci/console.h"
@@ -913,6 +914,25 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) {
// code concerning this via script patch.
s->variables[VAR_GLOBAL][0xB3].setOffset(SAVEGAMEID_OFFICIALRANGE_START + savegameId);
break;
+ case GID_JONES:
+ // HACK: The code that enables certain menu items isn't called when a game is restored from the
+ // launcher, or the "Restore game" option in the game's main menu - bugs #6537 and #6723.
+ // These menu entries are disabled when the game is launched, and are enabled when a new game is
+ // started. The code for enabling these entries is is all in script 1, room1::init, but that code
+ // path is never followed in these two cases (restoring game from the menu, or restoring a game
+ // from the ScummVM launcher). Thus, we perform the calls to enable the menus ourselves here.
+ // These two are needed when restoring from the launcher
+ // FIXME: The original interpreter saves and restores the menu state, so these attributes
+ // are automatically reset there. We may want to do the same.
+ g_sci->_gfxMenu->kernelSetAttribute(257 >> 8, 257 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> About Jones
+ g_sci->_gfxMenu->kernelSetAttribute(258 >> 8, 258 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Sierra -> Help
+ // The rest are normally enabled from room1::init
+ g_sci->_gfxMenu->kernelSetAttribute(769 >> 8, 769 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Options -> Delete current player
+ g_sci->_gfxMenu->kernelSetAttribute(513 >> 8, 513 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Save Game
+ g_sci->_gfxMenu->kernelSetAttribute(515 >> 8, 515 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Game -> Restore Game
+ g_sci->_gfxMenu->kernelSetAttribute(1025 >> 8, 1025 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Statistics
+ g_sci->_gfxMenu->kernelSetAttribute(1026 >> 8, 1026 & 0xFF, SCI_MENU_ATTRIBUTE_ENABLED, TRUE_REG); // Status -> Goals
+ break;
default:
break;
}
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index c2089bcd4d..ee2249bd9d 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -354,13 +354,16 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
}
textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16();
+
+ uint16 languageSplitter = 0;
+ Common::String splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter, sep);
#ifdef ENABLE_SCI32
if (g_sci->_gfxText32)
- g_sci->_gfxText32->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+ g_sci->_gfxText32->kernelTextSize(splitText.c_str(), font_nr, maxwidth, &textWidth, &textHeight);
else
#endif
- g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+ g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font_nr, maxwidth, &textWidth, &textHeight);
// One of the game texts in LB2 German contains loads of spaces in
// its end. We trim the text here, otherwise the graphics code will
@@ -376,7 +379,7 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
// Copy over the trimmed string...
s->_segMan->strcpy(argv[1], text.c_str());
// ...and recalculate bounding box dimensions
- g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight);
+ g_sci->_gfxText16->kernelTextSize(splitText.c_str(), languageSplitter, font_nr, maxwidth, &textWidth, &textHeight);
}
}
@@ -818,16 +821,29 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
if (!textReference.isNull())
text = s->_segMan->getString(textReference);
+ uint16 languageSplitter = 0;
+ Common::String splitText;
+
+ switch (type) {
+ case SCI_CONTROLS_TYPE_BUTTON:
+ case SCI_CONTROLS_TYPE_TEXTEDIT:
+ splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter, NULL);
+ break;
+ case SCI_CONTROLS_TYPE_TEXT:
+ splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter);
+ break;
+ }
+
switch (type) {
case SCI_CONTROLS_TYPE_BUTTON:
debugC(kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d", PRINT_REG(controlObject), x, y);
- g_sci->_gfxControls16->kernelDrawButton(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, style, hilite);
+ g_sci->_gfxControls16->kernelDrawButton(rect, controlObject, splitText.c_str(), languageSplitter, fontId, style, hilite);
return;
case SCI_CONTROLS_TYPE_TEXT:
alignment = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode));
debugC(kDebugLevelGraphics, "drawing text %04x:%04x ('%s') to %d,%d, mode=%d", PRINT_REG(controlObject), text.c_str(), x, y, alignment);
- g_sci->_gfxControls16->kernelDrawText(rect, controlObject, g_sci->strSplit(text.c_str()).c_str(), fontId, alignment, style, hilite);
+ g_sci->_gfxControls16->kernelDrawText(rect, controlObject, splitText.c_str(), languageSplitter, fontId, alignment, style, hilite);
s->r_acc = g_sci->_gfxText16->allocAndFillReferenceRectArray();
return;
@@ -841,7 +857,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
writeSelectorValue(s->_segMan, controlObject, SELECTOR(cursor), cursorPos);
}
debugC(kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d", PRINT_REG(controlObject), PRINT_REG(textReference), text.c_str(), x, y);
- g_sci->_gfxControls16->kernelDrawTextEdit(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, mode, style, cursorPos, maxChars, hilite);
+ g_sci->_gfxControls16->kernelDrawTextEdit(rect, controlObject, splitText.c_str(), languageSplitter, fontId, mode, style, cursorPos, maxChars, hilite);
return;
case SCI_CONTROLS_TYPE_ICON:
@@ -1165,8 +1181,11 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) {
argc--; argc--; argv++; argv++;
text = g_sci->getKernel()->lookupText(textp, index);
}
+
+ uint16 languageSplitter = 0;
+ Common::String splitText = g_sci->strSplitLanguage(text.c_str(), &languageSplitter);
- return g_sci->_gfxPaint16->kernelDisplay(g_sci->strSplit(text.c_str()).c_str(), argc, argv);
+ return g_sci->_gfxPaint16->kernelDisplay(splitText.c_str(), languageSplitter, argc, argv);
}
reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) {
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 56dad583e4..eef758a0d9 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -42,10 +42,12 @@ reg_t kStrCat(EngineState *s, int argc, reg_t *argv) {
Common::String s1 = s->_segMan->getString(argv[0]);
Common::String s2 = s->_segMan->getString(argv[1]);
- // The Japanese version of PQ2 splits the two strings here
- // (check bug #3396887).
- if (g_sci->getGameId() == GID_PQ2 &&
- g_sci->getLanguage() == Common::JA_JPN) {
+ // Japanese PC-9801 interpreter splits strings here
+ // see bug #5834
+ // Verified for Police Quest 2 + Quest For Glory 1
+ // However Space Quest 4 PC-9801 doesn't
+ if ((g_sci->getLanguage() == Common::JA_JPN)
+ && (getSciVersion() <= SCI_VERSION_01)) {
s1 = g_sci->strSplit(s1.c_str(), NULL);
s2 = g_sci->strSplit(s2.c_str(), NULL);
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index cdcdcc41e5..0b55425406 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -640,9 +640,11 @@ void SoundCommandParser::reconstructPlayList() {
initSoundResource(*i);
if ((*i)->status == kSoundPlaying) {
- // Sync the sound object's selectors related to playing with the stored
- // ones in the playlist, as they may have been invalidated when loading.
- // Refer to bug #3104624.
+ // WORKAROUND: PQ3 (German?) scripts can set volume negative in the
+ // sound object directly without going through DoSound.
+ // Since we re-read this selector when re-playing the sound after loading,
+ // this will lead to unexpected behaviour. As a workaround we
+ // sync the sound object's selectors here. (See bug #5501)
writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(loop), (*i)->loop);
writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(priority), (*i)->priority);
if (_soundVersion >= SCI_VERSION_1_EARLY)
@@ -844,6 +846,8 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const Common::Strin
if (voc)
voc->saveLoadWithSerializer(ser);
+ // TODO: SSCI (at least JonesCD, presumably more) also stores the Menu state
+
return true;
}
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 8bbbd713a6..03cd1d06e9 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -1214,6 +1214,26 @@ static const uint16 kq6CDPatchAudioTextSupportGirlInTheTower[] = {
PATCH_END
};
+// Fixes dual mode for scenes with Azure and Ariel (room 370)
+// Effectively same patch as the one for fixing "Girl In The Tower"
+// Applies to at least: PC-CD
+// Patched methods: rm370::init, caughtAtGateCD::changeState, caughtAtGateTXT::changeState, toLabyrinth::changeState
+// Fixes bug: #6750
+static const uint16 kq6CDSignatureAudioTextSupportAzureAriel[] = {
+ SIG_MAGICDWORD,
+ 0x89, 0x5a, // lsg global[5a]
+ 0x35, 0x02, // ldi 02
+ 0x1a, // eq?
+ 0x31, // bnt [jump-for-text-code]
+ SIG_END
+};
+
+static const uint16 kq6CDPatchAudioTextSupportAzureAriel[] = {
+ PATCH_ADDTOOFFSET(+4),
+ 0x12, // and
+ PATCH_END
+};
+
// Additional patch specifically for King's Quest 6
// Adds another button state for the text/audio button. We currently use the "speech" view for "dual" mode.
// View 947, loop 9, cel 0+1 -> "text"
@@ -1306,6 +1326,7 @@ static const SciScriptPatcherEntry kq6Signatures[] = {
{ false, 1009, "CD: audio + text support KQ6 Guards", 2, kq6CDSignatureAudioTextSupportGuards, kq6CDPatchAudioTextSupportGuards },
{ false, 1027, "CD: audio + text support KQ6 Stepmother", 1, kq6CDSignatureAudioTextSupportStepmother, kq6CDPatchAudioTextSupportJumpAlways },
{ false, 740, "CD: audio + text support KQ6 Girl In The Tower", 1, kq6CDSignatureAudioTextSupportGirlInTheTower, kq6CDPatchAudioTextSupportGirlInTheTower },
+ { false, 370, "CD: audio + text support KQ6 Azure & Ariel", 6, kq6CDSignatureAudioTextSupportAzureAriel, kq6CDPatchAudioTextSupportAzureAriel },
{ false, 903, "CD: audio + text support KQ6 menu", 1, kq6CDSignatureAudioTextMenuSupport, kq6CDPatchAudioTextMenuSupport },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -1917,6 +1938,43 @@ static const SciScriptPatcherEntry pq1vgaSignatures[] = {
};
// ===========================================================================
+// At the healer's house there is a bird's nest up on the tree.
+// The player can throw rocks at it until it falls to the ground.
+// The hero will then grab the item, that is in the nest.
+//
+// When running is active, the hero will not reach the actual destination
+// and because of that, the game will get stuck.
+//
+// We just change the coordinate of the destination slightly, so that walking,
+// sneaking and running work.
+//
+// This bug was fixed by Sierra at least in the Japanese PC-9801 version.
+// Applies to at least: English floppy (1.000, 1.012)
+// Responsible method: pickItUp::changeState (script 54)
+// Fixes bug: #6407
+static const uint16 qfg1egaSignatureThrowRockAtNest[] = {
+ 0x4a, 0x04, // send 04 (nest::x)
+ 0x36, // push
+ SIG_MAGICDWORD,
+ 0x35, 0x0f, // ldi 0f (15d)
+ 0x02, // add
+ 0x36, // push
+ SIG_END
+};
+
+static const uint16 qfg1egaPatchThrowRockAtNest[] = {
+ PATCH_ADDTOOFFSET(+3),
+ 0x35, 0x12, // ldi 12 (18d)
+ PATCH_END
+};
+
+// script, description, signature patch
+static const SciScriptPatcherEntry qfg1egaSignatures[] = {
+ { true, 54, "throw rock at nest while running", 1, qfg1egaSignatureThrowRockAtNest, qfg1egaPatchThrowRockAtNest },
+ SCI_SIGNATUREENTRY_TERMINATOR
+};
+
+// ===========================================================================
// script 215 of qfg1vga pointBox::doit actually processes button-presses
// during fighting with monsters. It strangely also calls kGetEvent. Because
// the main User::doit also calls kGetEvent it's pure luck, where the event
@@ -3036,6 +3094,9 @@ void ScriptPatcher::processScript(uint16 scriptNr, byte *scriptData, const uint3
case GID_PQ1:
signatureTable = pq1vgaSignatures;
break;
+ case GID_QFG1:
+ signatureTable = qfg1egaSignatures;
+ break;
case GID_QFG1VGA:
signatureTable = qfg1vgaSignatures;
break;
diff --git a/engines/sci/engine/script_patches.h b/engines/sci/engine/script_patches.h
index 0b35792949..7023ef327e 100644
--- a/engines/sci/engine/script_patches.h
+++ b/engines/sci/engine/script_patches.h
@@ -98,7 +98,7 @@ private:
void enablePatch(const SciScriptPatcherEntry *patchTable, const char *searchDescription);
int32 findSignature(const SciScriptPatcherEntry *patchEntry, SciScriptPatcherRuntimeEntry *runtimeEntry, const byte *scriptData, const uint32 scriptSize, bool isMacSci11);
void applyPatch(const SciScriptPatcherEntry *patchEntry, byte *scriptData, const uint32 scriptSize, int32 signatureOffset, bool isMacSci11);
-
+
Selector *_selectorIdTable;
SciScriptPatcherRuntimeEntry *_runtimeTable;
};
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 3738fd3dcb..58c2b8d3e3 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -371,7 +371,7 @@ void SegManager::freeHunkEntry(reg_t addr) {
HunkTable *ht = (HunkTable *)getSegment(addr.getSegment(), SEG_TYPE_HUNK);
if (!ht) {
- warning("Attempt to free Hunk from address %04x:%04x: Invalid segment type", PRINT_REG(addr));
+ warning("Attempt to free Hunk from address %04x:%04x: Invalid segment type %d", PRINT_REG(addr), getSegmentType(addr.getSegment()));
return;
}
diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp
index 7701822f6d..527c8f0ae0 100644
--- a/engines/sci/engine/state.cpp
+++ b/engines/sci/engine/state.cpp
@@ -203,59 +203,94 @@ static kLanguage charToLanguage(const char c) {
}
}
-Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage lang, kLanguage *lang2) const {
- kLanguage secondLang = K_LANG_NONE;
-
- const char *seeker = str.c_str();
- while (*seeker) {
- if ((*seeker == '%') || (*seeker == '#')) {
- secondLang = charToLanguage(*(seeker + 1));
-
- if (secondLang != K_LANG_NONE)
+Common::String SciEngine::getSciLanguageString(const Common::String &str, kLanguage requestedLanguage, kLanguage *secondaryLanguage, uint16 *languageSplitter) const {
+ kLanguage foundLanguage = K_LANG_NONE;
+ const byte *textPtr = (const byte *)str.c_str();
+ byte curChar = 0;
+ byte curChar2 = 0;
+
+ while (1) {
+ curChar = *textPtr;
+ if (!curChar)
+ break;
+
+ if ((curChar == '%') || (curChar == '#')) {
+ curChar2 = *(textPtr + 1);
+ foundLanguage = charToLanguage(curChar2);
+
+ if (foundLanguage != K_LANG_NONE) {
+ // Return language splitter
+ if (languageSplitter)
+ *languageSplitter = curChar | ( curChar2 << 8 );
+ // Return the secondary language found in the string
+ if (secondaryLanguage)
+ *secondaryLanguage = foundLanguage;
break;
+ }
}
-
- ++seeker;
+ textPtr++;
}
- // Return the secondary language found in the string
- if (lang2)
- *lang2 = secondLang;
-
- if (secondLang == lang) {
- if (*(++seeker) == 'J') {
+ if (foundLanguage == requestedLanguage) {
+ if (curChar2 == 'J') {
// Japanese including Kanji, displayed with system font
// Convert half-width characters to full-width equivalents
Common::String fullWidth;
- byte c;
+ uint16 mappedChar;
+
+ textPtr += 2; // skip over language splitter
+
+ while (1) {
+ curChar = *textPtr;
+
+ switch (curChar) {
+ case 0: // Terminator NUL
+ return fullWidth;
+ case '\\':
+ // "\n", "\N", "\r" and "\R" were overwritten with SPACE + 0x0D in PC-9801 SSCI
+ // inside GetLongest() (text16). We do it here, because it's much cleaner and
+ // we have to process the text here anyway.
+ // Occurs for example in Police Quest 2 intro
+ curChar2 = *(textPtr + 1);
+ switch (curChar2) {
+ case 'n':
+ case 'N':
+ case 'r':
+ case 'R':
+ fullWidth += ' ';
+ fullWidth += 0x0D; // CR
+ textPtr += 2;
+ continue;
+ }
+ }
+
+ textPtr++;
- while ((c = *(++seeker))) {
- uint16 mappedChar = s_halfWidthSJISMap[c];
+ mappedChar = s_halfWidthSJISMap[curChar];
if (mappedChar) {
fullWidth += mappedChar >> 8;
fullWidth += mappedChar & 0xFF;
} else {
// Copy double-byte character
- char c2 = *(++seeker);
- if (!c2) {
- error("SJIS character %02X is missing second byte", c);
+ curChar2 = *(textPtr++);
+ if (!curChar) {
+ error("SJIS character %02X is missing second byte", curChar);
break;
}
- fullWidth += c;
- fullWidth += c2;
+ fullWidth += curChar;
+ fullWidth += curChar2;
}
}
- return fullWidth;
} else {
- return Common::String(seeker + 1);
+ return Common::String((const char *)(textPtr + 2));
}
}
- if (*seeker)
- return Common::String(str.c_str(), seeker - str.c_str());
- else
- return str;
+ if (curChar)
+ return Common::String(str.c_str(), (const char *)textPtr - str.c_str());
+
+ return str;
}
kLanguage SciEngine::getSciLanguage() {
@@ -314,25 +349,25 @@ void SciEngine::setSciLanguage() {
setSciLanguage(getSciLanguage());
}
-Common::String SciEngine::strSplit(const char *str, const char *sep) {
- kLanguage lang = getSciLanguage();
- kLanguage subLang = K_LANG_NONE;
+Common::String SciEngine::strSplitLanguage(const char *str, uint16 *languageSplitter, const char *sep) {
+ kLanguage activeLanguage = getSciLanguage();
+ kLanguage subtitleLanguage = K_LANG_NONE;
if (SELECTOR(subtitleLang) != -1)
- subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(subtitleLang));
+ subtitleLanguage = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObjectAddress, SELECTOR(subtitleLang));
- kLanguage secondLang;
- Common::String retval = getSciLanguageString(str, lang, &secondLang);
+ kLanguage foundLanguage;
+ Common::String retval = getSciLanguageString(str, activeLanguage, &foundLanguage, languageSplitter);
// Don't add subtitle when separator is not set, subtitle language is not set, or
// string contains only one language
- if ((sep == NULL) || (subLang == K_LANG_NONE) || (secondLang == K_LANG_NONE))
+ if ((sep == NULL) || (subtitleLanguage == K_LANG_NONE) || (foundLanguage == K_LANG_NONE))
return retval;
// Add subtitle, unless the subtitle language doesn't match the languages in the string
- if ((subLang == K_LANG_ENGLISH) || (subLang == secondLang)) {
+ if ((subtitleLanguage == K_LANG_ENGLISH) || (subtitleLanguage == foundLanguage)) {
retval += sep;
- retval += getSciLanguageString(str, subLang);
+ retval += getSciLanguageString(str, subtitleLanguage);
}
return retval;
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 37e46b7a96..c5730b5345 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -44,7 +44,8 @@ const SciWorkaroundEntry arithmeticWorkarounds[] = {
{ GID_MOTHERGOOSEHIRES,90, 90, 0, "newGameButton", "select", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_ge: MUMG Deluxe, when selecting "New Game" in the main menu. It tries to compare an integer with a list. Needs to return false for the game to continue.
{ GID_PHANTASMAGORIA, 902, 0, 0, "", "export 7", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_shr: when starting a chapter in Phantasmagoria
{ GID_QFG1VGA, 301, 928, 0, "Blink", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_div: when entering the inn, gets called with 1 parameter, but 2nd parameter is used for div which happens to be an object
- { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer bug #5152
+ { GID_QFG2, 200, 200, 0, "astro", "messages", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_lsi: when getting asked for your name by the astrologer - bug #5152
+ { GID_QFG3, 780, 999, 0, "", "export 6", -1, 0, { WORKAROUND_FAKE, 0 } }, // op_add: trying to talk to yourself at the top of the giant tree - bug #6692
{ GID_QFG4, 710,64941, 0, "RandCycle", "doit", -1, 0, { WORKAROUND_FAKE, 1 } }, // op_gt: when the tentacle appears in the third room of the caves
SCI_WORKAROUNDENTRY_TERMINATOR
};
@@ -90,7 +91,8 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
{ GID_HOYLE4, 700, -1, 1, "BridgeDefense", "think", -1, -1, { WORKAROUND_FAKE, 0 } }, // sometimes while playing bridge, temp var 3, 17 and others, objects LeadReturn_Trump, ThirdSeat_Trump and others
{ GID_HOYLE4, 700, 730, 1, "BridgeDefense", "beatTheirBest", -1, 3, { WORKAROUND_FAKE, 0 } }, // rarely while playing bridge
{ GID_HOYLE4, 700, -1, 1, "Code", "doit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when placing a bid in bridge (always), temp var 11, 24, 27, 46, 75, objects compete_tree, compwe_tree, other1_tree, b1 - bugs #5663 and #5794
- { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, -1, { WORKAROUND_FAKE, 0 } }, // when saving the game (may also occur in other situations) - bug #6601
+ { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, 0, { WORKAROUND_FAKE, 118 } }, // when saving the game (may also occur in other situations) - bug #6601, bug #6614
+ { GID_HOYLE4, 700, 921, 0, "Print", "addEdit", -1, 1, { WORKAROUND_FAKE, 1 } }, // see above, Text-control saves its coordinates to temp[0] and temp[1], Edit-control adjusts to those uninitialized temps, who by accident were left over from the Text-control
{ GID_HOYLE4, 300, 300, 0, "", "export 2", 0x1d4d, 0, { WORKAROUND_FAKE, 0 } }, // after passing around cards in hearts
{ GID_HOYLE4, 400, 400, 1, "GinHand", "calcRuns", -1, 4, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Gin Rummy (e.g. when knocking and placing a card) - bug #5665
{ GID_HOYLE4, 500, 17, 1, "Character", "say", -1, 504, { WORKAROUND_FAKE, 0 } }, // sometimes while playing Cribbage (e.g. when the opponent says "Last Card") - bug #5662