aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--audio/decoders/mp3.cpp16
-rw-r--r--common/config-manager.cpp10
-rw-r--r--engines/advancedDetector.cpp2
-rw-r--r--engines/mads/msurface.h2
-rw-r--r--engines/mads/nebular/dialogs_nebular.cpp1
-rw-r--r--engines/mads/nebular/menu_nebular.cpp10
-rw-r--r--engines/saga/shorten.cpp60
-rw-r--r--engines/sci/detection_tables.h19
-rw-r--r--engines/sci/engine/features.cpp6
-rw-r--r--engines/sci/engine/kernel_tables.h3
-rw-r--r--engines/sci/engine/seg_manager.cpp2
-rw-r--r--engines/sci/engine/workarounds.cpp3
-rw-r--r--engines/sci/graphics/frameout.cpp6
-rw-r--r--engines/sci/parser/said.cpp35
-rw-r--r--engines/sci/parser/vocabulary.cpp15
-rw-r--r--engines/scumm/charset.cpp95
-rw-r--r--engines/scumm/charset.h29
-rw-r--r--engines/scumm/input.cpp5
-rw-r--r--engines/scumm/nut_renderer.cpp55
-rw-r--r--engines/scumm/smush/smush_font.cpp66
-rw-r--r--engines/scumm/sound.cpp9
-rw-r--r--engines/toltecs/detection.cpp14
-rw-r--r--engines/toon/toon.cpp22
-rw-r--r--engines/zvision/scripting/actions.cpp12
-rw-r--r--engines/zvision/scripting/controls/input_control.cpp2
-rw-r--r--test/common/rendermode.h1
26 files changed, 347 insertions, 153 deletions
diff --git a/audio/decoders/mp3.cpp b/audio/decoders/mp3.cpp
index 091f64569d..c1b3faaeb1 100644
--- a/audio/decoders/mp3.cpp
+++ b/audio/decoders/mp3.cpp
@@ -59,7 +59,7 @@ protected:
State _state;
Timestamp _length;
- mad_timer_t _totalTime;
+ mad_timer_t _curTime;
mad_stream _stream;
mad_frame _frame;
@@ -99,7 +99,7 @@ MP3Stream::MP3Stream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag
_posInFrame(0),
_state(MP3_STATE_INIT),
_length(0, 1000),
- _totalTime(mad_timer_zero) {
+ _curTime(mad_timer_zero) {
// The MAD_BUFFER_GUARD must always contain zeros (the reason
// for this is that the Layer III Huffman decoder of libMAD
@@ -119,7 +119,7 @@ MP3Stream::MP3Stream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag
// Note that we allow "MAD_ERROR_BUFLEN" as error code here, since according
// to mad.h it is also set on EOF.
if ((_stream.error == MAD_ERROR_NONE || _stream.error == MAD_ERROR_BUFLEN) && getRate() > 0)
- _length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate());
+ _length = Timestamp(mad_timer_count(_curTime, MAD_UNITS_MILLISECONDS), getRate());
deinitStream();
@@ -166,6 +166,8 @@ void MP3Stream::decodeMP3Data() {
}
}
+ // Sum up the total playback time so far
+ mad_timer_add(&_curTime, _frame.header.duration);
// Synthesize PCM data
mad_synth_frame(&_synth, &_frame);
_posInFrame = 0;
@@ -220,10 +222,10 @@ bool MP3Stream::seek(const Timestamp &where) {
mad_timer_t destination;
mad_timer_set(&destination, time / 1000, time % 1000, 1000);
- if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0)
+ if (_state != MP3_STATE_READY || mad_timer_compare(destination, _curTime) < 0)
initStream();
- while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
+ while (mad_timer_compare(destination, _curTime) > 0 && _state != MP3_STATE_EOS)
readHeader();
decodeMP3Data();
@@ -242,7 +244,7 @@ void MP3Stream::initStream() {
// Reset the stream data
_inStream->seek(0, SEEK_SET);
- _totalTime = mad_timer_zero;
+ _curTime = mad_timer_zero;
_posInFrame = 0;
// Update state
@@ -280,7 +282,7 @@ void MP3Stream::readHeader() {
}
// Sum up the total playback time so far
- mad_timer_add(&_totalTime, _frame.header.duration);
+ mad_timer_add(&_curTime, _frame.header.duration);
break;
}
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index feb3ddcf56..04b62371b2 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -597,7 +597,7 @@ void ConfigManager::setActiveDomain(const String &domName) {
_activeDomain = 0;
} else {
assert(isValidDomainName(domName));
- _activeDomain = & _gameDomains[domName];
+ _activeDomain = &_gameDomains[domName];
}
_activeDomainName = domName;
}
@@ -626,6 +626,10 @@ void ConfigManager::addMiscDomain(const String &domName) {
void ConfigManager::removeGameDomain(const String &domName) {
assert(!domName.empty());
assert(isValidDomainName(domName));
+ if (domName == _activeDomainName) {
+ _activeDomainName = "";
+ _activeDomain = 0;
+ }
_gameDomains.erase(domName);
}
@@ -638,6 +642,10 @@ void ConfigManager::removeMiscDomain(const String &domName) {
void ConfigManager::renameGameDomain(const String &oldName, const String &newName) {
renameDomain(oldName, newName, _gameDomains);
+ if (_activeDomainName == oldName) {
+ _activeDomainName = newName;
+ _activeDomain = &_gameDomains[newName];
+ }
}
void ConfigManager::renameMiscDomain(const String &oldName, const String &newName) {
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index fa23f5fa1a..72629a833e 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -122,7 +122,7 @@ bool cleanupPirated(ADGameDescList &matched) {
// We ruled out all variants and now have nothing
if (matched.empty()) {
- warning("Illegitimate game copy detected. We give no support in such cases %d", matched.size());
+ warning("Illegitimate game copy detected. We provide no support in such cases");
return true;
}
}
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index 23e0a03985..cd6bde1271 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -230,7 +230,7 @@ public:
/**
* Constructor
*/
- DepthSurface(MADSEngine *vm) : _vm(vm) {}
+ DepthSurface(MADSEngine *vm) : _vm(vm), _depthStyle(0) {}
/**
* Returns the depth at a given position
diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp
index d4b277d856..f3eddc3fbb 100644
--- a/engines/mads/nebular/dialogs_nebular.cpp
+++ b/engines/mads/nebular/dialogs_nebular.cpp
@@ -638,6 +638,7 @@ GameDialog::GameDialog(MADSEngine *vm) : FullScreenDialog(vm) {
scene.clearVocab();
scene._dynamicHotspots.clear();
_vm->_dialogs->_defaultPosition = Common::Point(-1, -1);
+ _menuSpritesIndex = 0;
}
void GameDialog::display() {
diff --git a/engines/mads/nebular/menu_nebular.cpp b/engines/mads/nebular/menu_nebular.cpp
index cb8f56bd05..98eb669616 100644
--- a/engines/mads/nebular/menu_nebular.cpp
+++ b/engines/mads/nebular/menu_nebular.cpp
@@ -83,6 +83,9 @@ MainMenu::MainMenu(MADSEngine *vm): MenuView(vm) {
_highlightedIndex = -1;
_selectedIndex = -1;
_buttonDown = false;
+
+ for (int i = 0; i < 7; ++i)
+ _menuItems[i] = nullptr;
}
MainMenu::~MainMenu() {
@@ -408,7 +411,7 @@ char TextView::_resourceName[100];
void TextView::execute(MADSEngine *vm, const Common::String &resName) {
assert(resName.size() < 100);
- strcpy(_resourceName, resName.c_str());
+ strncpy(_resourceName, resName.c_str(), sizeof(_resourceName));
vm->_dialogs->_pendingDialog = DIALOG_TEXTVIEW;
}
@@ -460,7 +463,7 @@ void TextView::processLines() {
processCommand();
// Copy rest of line (if any) to start of buffer
- strcpy(_currentLine, cEnd + 1);
+ strncpy(_currentLine, cEnd + 1, sizeof(_currentLine));
cStart = strchr(_currentLine, '[');
}
@@ -631,12 +634,13 @@ char AnimationView::_resourceName[100];
void AnimationView::execute(MADSEngine *vm, const Common::String &resName) {
assert(resName.size() < 100);
- strcpy(_resourceName, resName.c_str());
+ strncpy(_resourceName, resName.c_str(), sizeof(_resourceName));
vm->_dialogs->_pendingDialog = DIALOG_ANIMVIEW;
}
AnimationView::AnimationView(MADSEngine *vm) : MenuView(vm) {
_soundDriverLoaded = false;
+ _previousUpdate = 0;
}
void AnimationView::load() {
diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp
index 426430c892..edb12a3dd9 100644
--- a/engines/saga/shorten.cpp
+++ b/engines/saga/shorten.cpp
@@ -29,6 +29,8 @@
// Based on etree's Shorten tool, version 3.6.1
// http://etree.org/shnutils/shorten/
+// and
+// https://github.com/soiaf/Java-Shorten-decoder
// FIXME: This doesn't work yet correctly
@@ -154,6 +156,7 @@ uint32 ShortenGolombReader::getUint32(uint32 numBits) {
byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, byte &flags) {
int32 *buffer[2], *offset[2]; // up to 2 channels
+ int32 *oldValues[2];
byte *unpackedBuffer = 0;
byte *pBuf = unpackedBuffer;
int prevSize = 0;
@@ -190,15 +193,18 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
switch (type) {
case kTypeS8:
+ mean = 0;
break;
case kTypeU8:
flags |= Audio::FLAG_UNSIGNED;
+ mean = 0x80;
break;
case kTypeS16LH:
flags |= Audio::FLAG_LITTLE_ENDIAN;
// fallthrough
case kTypeS16HL:
flags |= Audio::FLAG_16BITS;
+ mean = 0;
break;
case kTypeU16LH:
flags |= Audio::FLAG_LITTLE_ENDIAN;
@@ -206,6 +212,7 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
case kTypeU16HL:
flags |= Audio::FLAG_16BITS;
flags |= Audio::FLAG_UNSIGNED;
+ mean = 0x8000;
break;
case kTypeWAV:
// TODO: Perhaps implement this if we find WAV Shorten encoded files
@@ -264,8 +271,10 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
for (i = 0; i < channels; i++) {
buffer[i] = (int32 *)malloc((blockSize + wrap) * 4);
offset[i] = (int32 *)malloc((MAX<uint32>(1, mean)) * 4);
+ oldValues[i] = (int32 *)malloc(64 * 4);
memset(buffer[i], 0, (blockSize + wrap) * 4);
memset(offset[i], 0, (MAX<uint32>(1, mean)) * 4);
+ memset(oldValues[i], 0, 64 * 4);
}
if (maxLPC > 0)
@@ -329,9 +338,6 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
channelOffset = (channelOffset >> (bitShift - 1)) >> 1;
}
- // FIXME: The original code in this bit tries to modify memory outside of the array (negative indices)
- // in cases kCmdDiff1, kCmdDiff2 and kCmdDiff3
- // I've removed those invalid writes, since they happen all the time (even when curChannel is 0)
switch (cmd) {
case kCmdZero:
for (i = 0; i < blockSize; i++)
@@ -342,22 +348,34 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
buffer[curChannel][i] = gReader->getSRice(energy) + channelOffset;
break;
case kCmdDiff1:
- gReader->getSRice(energy); // i = 0 (to fix invalid table/memory access)
- for (i = 1; i < blockSize; i++)
- buffer[curChannel][i] = gReader->getSRice(energy) + buffer[curChannel][i - 1];
+ for (i = 0; i < blockSize; i++) {
+ if (i == 0)
+ buffer[curChannel][i] = gReader->getSRice(energy) + oldValues[curChannel][0];
+ else
+ buffer[curChannel][i] = gReader->getSRice(energy) + buffer[curChannel][i - 1];
+ }
break;
case kCmdDiff2:
- gReader->getSRice(energy); // i = 0 (to fix invalid table/memory access)
- gReader->getSRice(energy); // i = 1 (to fix invalid table/memory access)
- for (i = 2; i < blockSize; i++)
- buffer[curChannel][i] = gReader->getSRice(energy) + 2 * buffer[curChannel][i - 1] - buffer[curChannel][i - 2];
+ for (i = 0; i < blockSize; i++) {
+ if (i == 0)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 2 * oldValues[curChannel][0] - oldValues[curChannel][1];
+ else if (i == 1)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 2 * buffer[curChannel][0] - oldValues[curChannel][0];
+ else
+ buffer[curChannel][i] = gReader->getSRice(energy) + 2 * buffer[curChannel][i - 1] - buffer[curChannel][i - 2];
+ }
break;
case kCmdDiff3:
- gReader->getSRice(energy); // i = 0 (to fix invalid table/memory access)
- gReader->getSRice(energy); // i = 1 (to fix invalid table/memory access)
- gReader->getSRice(energy); // i = 2 (to fix invalid table/memory access)
- for (i = 3; i < blockSize; i++)
- buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (buffer[curChannel][i - 1] - buffer[curChannel][i - 2]) + buffer[curChannel][i - 3];
+ for (i = 0; i < blockSize; i++) {
+ if (i == 0)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (oldValues[curChannel][0] - oldValues[curChannel][1]) + oldValues[curChannel][2];
+ else if (i == 1)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (buffer[curChannel][0] - oldValues[curChannel][0]) + oldValues[curChannel][1];
+ else if (i == 2)
+ buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (buffer[curChannel][1] - buffer[curChannel][0]) + oldValues[curChannel][0];
+ else
+ buffer[curChannel][i] = gReader->getSRice(energy) + 3 * (buffer[curChannel][i - 1] - buffer[curChannel][i - 2]) + buffer[curChannel][i - 3];
+ }
break;
case kCmdQLPC:
lpcNum = gReader->getURice(2);
@@ -417,10 +435,12 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
// Do the wrap
- // FIXME: removed for now, as this corrupts the heap, because it
- // accesses negative array indices
- //for (int32 k = -wrap; k < 0; k++)
- // buffer[curChannel][k] = buffer[curChannel][k + blockSize];
+ for (i = 0; i < 64; ++i)
+ oldValues[curChannel][i] = 0;
+
+ int arrayTerminator = MIN<int>(64, blockSize);
+ for (i = 0; i < arrayTerminator; ++i)
+ oldValues[curChannel][i] = buffer[curChannel][blockSize - (i + 1)];
// Fix bitshift
if (bitShift > 0) {
@@ -495,6 +515,7 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
for (i = 0; i < channels; i++) {
free(buffer[i]);
free(offset[i]);
+ free(oldValues[i]);
}
if (maxLPC > 0)
@@ -516,6 +537,7 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by
for (i = 0; i < channels; i++) {
free(buffer[i]);
free(offset[i]);
+ free(oldValues[i]);
}
if (maxLPC > 0)
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 344298ce9a..91b3c45c6e 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -2607,6 +2607,25 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+ // Phantasmagoria - French DOS
+ // Supplied by Kervala in bug #6574
+ {"phantasmagoria", "", {
+ {"resmap.001", 0, "4da82dd336d4b9cd8c16f3cc11f0c615", 11524},
+ {"ressci.001", 0, "3aae6559aa1df273bc542d5ac6330d75", 69963685},
+ {"resmap.002", 0, "4f40f43f2b60bf765864433069752bb9", 12064},
+ {"ressci.002", 0, "3aae6559aa1df273bc542d5ac6330d75", 78362841},
+ {"resmap.003", 0, "6a392a86f14b6ddb4422978ee71e54ac", 12340},
+ {"ressci.003", 0, "3aae6559aa1df273bc542d5ac6330d75", 80431189},
+ {"resmap.004", 0, "df2e9462c41202de5f3843908c95a715", 12562},
+ {"ressci.004", 0, "3aae6559aa1df273bc542d5ac6330d75", 82542844},
+ {"resmap.005", 0, "43efd3fe834286c70a2c8b4cd747c1e2", 12616},
+ {"ressci.005", 0, "3aae6559aa1df273bc542d5ac6330d75", 83790486},
+ {"resmap.006", 0, "b3065e54a00190752a06dacd201b5058", 12538},
+ {"ressci.006", 0, "3aae6559aa1df273bc542d5ac6330d75", 85415107},
+ {"resmap.007", 0, "5633960bc106c39ca91d2d8fce18fd2d", 7984},
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformDOS, ADGF_UNSTABLE, GUIO5(GUIO_NOSPEECH, GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
+
// Phantasmagoria - English DOS Demo
// Executable scanning reports "2.100.002"
{"phantasmagoria", "Demo", {
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_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/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/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index 37e46b7a96..ea4dc2fe71 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
};
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index a322eb8e61..91b5b25e99 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -782,9 +782,13 @@ void GfxFrameout::kernelFrameout() {
// TODO: For some reason, the top left nsRect coordinates get
// swapped in the GK1 inventory screen, investigate why.
+ // This is also needed for GK1 rooms 710 and 720 (catacombs, inner and
+ // outer circle), for handling the tiles and talking to Wolfgang.
// HACK: Fix the coordinates by explicitly setting them here.
Common::Rect objNSRect = g_sci->_gfxCompare->getNSRect(itemEntry->object);
- if (objNSRect.top == nsRect.left && objNSRect.left == nsRect.top && nsRect.top != 0 && nsRect.left != 0) {
+ uint16 roomNumber = g_sci->getEngineState()->currentRoomNumber();
+ if (objNSRect.top == nsRect.left && objNSRect.left == nsRect.top && nsRect.top != 0 && nsRect.left != 0 ||
+ (g_sci->getGameId() == GID_GK1 && (roomNumber == 710 || roomNumber == 720))) {
g_sci->_gfxCompare->setNSRect(itemEntry->object, nsRect);
}
}
diff --git a/engines/sci/parser/said.cpp b/engines/sci/parser/said.cpp
index 693bbec744..27ebc58704 100644
--- a/engines/sci/parser/said.cpp
+++ b/engines/sci/parser/said.cpp
@@ -186,8 +186,7 @@ static bool parseList(ParseTreeNode* parentNode);
static bool parseListEntry(ParseTreeNode* parentNode);
static bool parseWord(ParseTreeNode* parentNode);
-static bool parseWord(ParseTreeNode* parentNode)
-{
+static bool parseWord(ParseTreeNode* parentNode) {
int token = said_tokens[said_token];
if (token & 0x8000)
return false;
@@ -201,8 +200,7 @@ static bool parseWord(ParseTreeNode* parentNode)
return true;
}
-static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty)
-{
+static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -259,8 +257,7 @@ static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty)
return false;
}
-static bool parsePart3(ParseTreeNode* parentNode, bool& nonempty)
-{
+static bool parsePart3(ParseTreeNode* parentNode, bool& nonempty) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -318,8 +315,7 @@ static bool parsePart3(ParseTreeNode* parentNode, bool& nonempty)
}
-static bool parseSlash(ParseTreeNode* parentNode)
-{
+static bool parseSlash(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -343,8 +339,7 @@ static bool parseSlash(ParseTreeNode* parentNode)
}
-static bool parseRef(ParseTreeNode* parentNode)
-{
+static bool parseRef(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -411,8 +406,7 @@ static bool parseRef(ParseTreeNode* parentNode)
return false;
}
-static bool parseComma(ParseTreeNode* parentNode)
-{
+static bool parseComma(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -435,8 +429,7 @@ static bool parseComma(ParseTreeNode* parentNode)
return false;
}
-static bool parseListEntry(ParseTreeNode* parentNode)
-{
+static bool parseListEntry(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -494,8 +487,7 @@ static bool parseListEntry(ParseTreeNode* parentNode)
return false;
}
-static bool parseList(ParseTreeNode* parentNode)
-{
+static bool parseList(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -524,8 +516,7 @@ static bool parseList(ParseTreeNode* parentNode)
return false;
}
-static bool parseExpr(ParseTreeNode* parentNode)
-{
+static bool parseExpr(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -546,7 +537,6 @@ static bool parseExpr(ParseTreeNode* parentNode)
said_attach_subtree(newParent, 0x141, 0x14F, newNode);
newParent = newParent->right;
-
}
found = parseRef(newParent);
@@ -561,8 +551,7 @@ static bool parseExpr(ParseTreeNode* parentNode)
return false;
}
-static bool parseSpec(ParseTreeNode* parentNode)
-{
+static bool parseSpec(ParseTreeNode* parentNode) {
// Store current state for rolling back if we fail
int curToken = said_token;
int curTreePos = said_tree_pos;
@@ -748,9 +737,7 @@ static void node_print_desc(ParseTreeNode *) { }
-
-static int matchTrees(ParseTreeNode* parseT, ParseTreeNode* saidT)
-{
+static int matchTrees(ParseTreeNode* parseT, ParseTreeNode* saidT) {
outputDepth++;
scidprintf("%*smatchTrees on ", outputDepth, "");
node_print_desc(parseT);
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index b4a223dcff..3344b79e26 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -530,18 +530,19 @@ bool Vocabulary::tokenizeString(ResultWordListList &retval, const char *sentence
*error = NULL;
do {
-
c = sentence[pos_in_sentence++];
+
if (Common::isAlnum(c) || (c == '-' && wordLen) || (c >= 0x80)) {
currentWord[wordLen] = lowerCaseMap[c];
++wordLen;
- }
- // Continue on this word */
- // Words may contain a '-', but may not
- // start with one.
- else {
- if (wordLen) { // Finished a word?
+ } else if (c == '\'' && wordLen && (sentence[pos_in_sentence] == 's' || sentence[pos_in_sentence] == 'S')) {
+ // Skip apostrophe-s at the end of the word, if it exists
+ pos_in_sentence++; // skip the 's'
+ } else {
+ // Continue on this word. Words may contain a '-', but may not start with
+ // one.
+ if (wordLen) { // Finished a word?
ResultWordList lookup_result;
// Look it up
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 185ebbce6e..e546c805b5 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -253,7 +253,7 @@ CharsetRenderer::~CharsetRenderer() {
CharsetRendererCommon::CharsetRendererCommon(ScummEngine *vm)
: CharsetRenderer(vm), _bytesPerPixel(0), _fontHeight(0), _numChars(0) {
- _shadowMode = false;
+ _enableShadow = false;
_shadowColor = 0;
}
@@ -392,6 +392,10 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) {
} else if (chr & 0x80) {
pos++;
width += _vm->_2byteWidth;
+ // Original keeps glyph width and character dimensions separately
+ if (_vm->_language == Common::KO_KOR || _vm->_language == Common::ZH_TWN) {
+ width++;
+ }
continue;
}
}
@@ -478,6 +482,12 @@ void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
} else if (chr & 0x80) {
pos++;
curw += _vm->_2byteWidth;
+ // Original keeps glyph width and character dimensions separately
+ if (_vm->_language == Common::KO_KOR || _vm->_language == Common::ZH_TWN) {
+ curw++;
+ }
+ } else {
+ curw += getCharWidth(chr);
}
} else {
curw += getCharWidth(chr);
@@ -507,12 +517,17 @@ int CharsetRendererV3::getCharWidth(uint16 chr) {
return spacing;
}
-void CharsetRendererV3::enableShadow(bool enable) {
+void CharsetRendererPC::enableShadow(bool enable) {
_shadowColor = 0;
- _shadowMode = enable;
+ _enableShadow = enable;
+
+ if (_vm->_game.version >= 7 && _vm->_language == Common::KO_KOR)
+ _shadowType = kHorizontalShadowType;
+ else
+ _shadowType = kNormalShadowType;
}
-void CharsetRendererV3::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
+void CharsetRendererPC::drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height) {
byte *dst = (byte *)dest.getBasePtr(x, y);
byte bits = 0;
@@ -525,8 +540,12 @@ void CharsetRendererV3::drawBits1(Graphics::Surface &dest, int x, int y, const b
if ((x % 8) == 0)
bits = *src++;
if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
- if (_shadowMode)
- dst[1] = dst2[0] = dst2[1] = _shadowColor;
+ if (_enableShadow) {
+ if (_shadowType == kNormalShadowType)
+ dst[1] = dst2[0] = dst2[1] = _shadowColor;
+ else if (_shadowType == kHorizontalShadowType)
+ dst[1] = _shadowColor;
+ }
dst[0] = col;
}
dst += dest.format.bytesPerPixel;
@@ -615,7 +634,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (_left + origWidth > _right + 1)
return;
- if (_shadowMode) {
+ if (_enableShadow) {
width++;
height++;
}
@@ -658,7 +677,7 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_shadowMode)
+ if (_enableShadow)
_str.right++;
}
@@ -776,11 +795,15 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
printCharIntern(is2byte, _charPtr, _origWidth, _origHeight, _width, _height, vs, ignoreCharsetMask);
+ // Original keeps glyph width and character dimensions separately
+ if ((_vm->_language == Common::ZH_TWN || _vm->_language == Common::KO_KOR) && is2byte)
+ _origWidth++;
+
_left += _origWidth;
if (_str.right < _left) {
_str.right = _left;
- if (_vm->_game.platform != Common::kPlatformFMTowns && _shadowMode)
+ if (_vm->_game.platform != Common::kPlatformFMTowns && _enableShadow)
_str.right++;
}
@@ -844,7 +867,10 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
drawTop = _top - _vm->_screenTop;
}
- drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight);
+ if (is2byte && _vm->_game.platform != Common::kPlatformFMTowns)
+ drawBits1(dstSurface, _left, drawTop, charPtr, drawTop, origWidth, origHeight);
+ else
+ drawBitsN(dstSurface, dstPtr, charPtr, *_fontPtr, drawTop, origWidth, origHeight);
if (_blitAlso && vs->hasTwoBuffers) {
// FIXME: Revisiting this code, I think the _blitAlso mode is likely broken
@@ -884,6 +910,24 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
}
bool CharsetRendererClassic::prepareDraw(uint16 chr) {
+ bool is2byte = (chr >= 256 && _vm->_useCJKMode);
+ if (is2byte) {
+ if (_vm->_language == Common::KO_KOR)
+ enableShadow(true);
+
+ _charPtr = _vm->get2byteCharPtr(chr);
+ _width = _origWidth = _vm->_2byteWidth;
+ _height = _origHeight = _vm->_2byteHeight;
+ _offsX = _offsY = 0;
+
+ if (_enableShadow) {
+ _width++;
+ _height++;
+ }
+
+ return true;
+ }
+
uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4);
assert(charOffs < 0x14000);
if (!charOffs)
@@ -908,8 +952,14 @@ bool CharsetRendererClassic::prepareDraw(uint16 chr) {
void CharsetRendererClassic::drawChar(int chr, Graphics::Surface &s, int x, int y) {
if (!prepareDraw(chr))
return;
+
byte *dst = (byte *)s.getBasePtr(x, y);
- drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height);
+
+ bool is2byte = (_vm->_useCJKMode && chr >= 256);
+ if (is2byte)
+ drawBits1(s, x, y, _charPtr, y, _width, _height);
+ else
+ drawBitsN(s, dst, _charPtr, *_fontPtr, y, _width, _height);
}
void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) {
@@ -982,7 +1032,7 @@ int CharsetRendererTownsV3::getFontHeight() {
void CharsetRendererTownsV3::enableShadow(bool enable) {
_shadowColor = 8;
- _shadowMode = enable;
+ _enableShadow = enable;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_shadowColor = 0x88;
@@ -1027,13 +1077,13 @@ void CharsetRendererTownsV3::drawBits1(Graphics::Surface &dest, int x, int y, co
bits = *src++;
if ((bits & revBitMask(x % 8)) && y + drawTop >= 0) {
if (dest.format.bytesPerPixel == 2) {
- if (_shadowMode) {
+ if (_enableShadow) {
WRITE_UINT16(dst + 2, _vm->_16BitPalette[_shadowColor]);
WRITE_UINT16(dst + dest.pitch, _vm->_16BitPalette[_shadowColor]);
}
WRITE_UINT16(dst, _vm->_16BitPalette[_color]);
} else {
- if (_shadowMode) {
+ if (_enableShadow) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (scale2x) {
dst[2] = dst[3] = dst2[2] = dst2[3] = _shadowColor;
@@ -1124,11 +1174,11 @@ void CharsetRendererPCE::drawBits1(Graphics::Surface &dest, int x, int y, const
bits = *src++;
if ((bits & revBitMask(bitCount % 8)) && y + drawTop >= 0) {
if (dest.format.bytesPerPixel == 2) {
- if (_shadowMode)
+ if (_enableShadow)
WRITE_UINT16(dst + dest.pitch + 2, _vm->_16BitPalette[_shadowColor]);
WRITE_UINT16(dst, _vm->_16BitPalette[_color]);
} else {
- if (_shadowMode)
+ if (_enableShadow)
*(dst + dest.pitch + 1) = _shadowColor;
*dst = _color;
}
@@ -1227,7 +1277,8 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
int width = _current->getCharWidth(chr);
int height = _current->getCharHeight(chr);
- if (chr >= 256 && _vm->_useCJKMode)
+ bool is2byte = chr >= 256 && _vm->_useCJKMode;
+ if (is2byte)
width = _vm->_2byteWidth;
shadow.right = _left + width;
@@ -1259,8 +1310,8 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
_str.left = _left;
// Original keeps glyph width and character dimensions separately
- if (_vm->_language == Common::ZH_TWN && width == 16)
- width = 17;
+ if ((_vm->_language == Common::ZH_TWN || _vm->_language == Common::KO_KOR) && is2byte)
+ width++;
_left += width;
@@ -1327,7 +1378,7 @@ void CharsetRendererNES::printChar(int chr, bool ignoreCharsetMask) {
if (_str.right < _left) {
_str.right = _left;
- if (_shadowMode)
+ if (_enableShadow)
_str.right++;
}
@@ -1483,7 +1534,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) {
_origHeight = _height = _vm->_2byteHeight;
_charPtr = _vm->get2byteCharPtr(chr);
_offsX = _offsY = 0;
- if (_shadowMode) {
+ if (_enableShadow) {
_width++;
_height++;
}
@@ -1495,7 +1546,7 @@ bool CharsetRendererTownsClassic::prepareDraw(uint16 chr) {
}
void CharsetRendererTownsClassic::setupShadowMode() {
- _shadowMode = true;
+ _enableShadow = true;
_shadowColor = _vm->_townsCharsetColorMap[0];
assert(_vm->_cjkFont);
diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h
index 5a9977b7d6..b4b3d88ccd 100644
--- a/engines/scumm/charset.h
+++ b/engines/scumm/charset.h
@@ -100,7 +100,7 @@ protected:
int _numChars;
byte _shadowColor;
- bool _shadowMode;
+ bool _enableShadow;
public:
CharsetRendererCommon(ScummEngine *vm);
@@ -110,7 +110,24 @@ public:
virtual int getFontHeight();
};
-class CharsetRendererClassic : public CharsetRendererCommon {
+class CharsetRendererPC : public CharsetRendererCommon {
+ enum ShadowType {
+ kNoShadowType,
+ kNormalShadowType,
+ kHorizontalShadowType
+ };
+
+ ShadowType _shadowType;
+
+protected:
+ virtual void enableShadow(bool enable);
+ virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height);
+
+public:
+ CharsetRendererPC(ScummEngine *vm) : CharsetRendererCommon(vm), _shadowType(kNoShadowType) { }
+};
+
+class CharsetRendererClassic : public CharsetRendererPC {
protected:
virtual void drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height);
void printCharIntern(bool is2byte, const byte *charPtr, int origWidth, int origHeight, int width, int height, VirtScreen *vs, bool ignoreCharsetMask);
@@ -124,7 +141,7 @@ protected:
VirtScreenNumber _drawScreen;
public:
- CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
+ CharsetRendererClassic(ScummEngine *vm) : CharsetRendererPC(vm) {}
void printChar(int chr, bool ignoreCharsetMask);
void drawChar(int chr, Graphics::Surface &s, int x, int y);
@@ -170,10 +187,8 @@ public:
int getCharWidth(uint16 chr) { return 8; }
};
-class CharsetRendererV3 : public CharsetRendererCommon {
+class CharsetRendererV3 : public CharsetRendererPC {
protected:
- virtual void enableShadow(bool enable);
- virtual void drawBits1(Graphics::Surface &dest, int x, int y, const byte *src, int drawTop, int width, int height);
virtual int getDrawWidthIntern(uint16 chr);
virtual int getDrawHeightIntern(uint16 chr);
virtual void setDrawCharIntern(uint16 chr) {}
@@ -181,7 +196,7 @@ protected:
const byte *_widthTable;
public:
- CharsetRendererV3(ScummEngine *vm) : CharsetRendererCommon(vm) {}
+ CharsetRendererV3(ScummEngine *vm) : CharsetRendererPC(vm) {}
void printChar(int chr, bool ignoreCharsetMask);
void drawChar(int chr, Graphics::Surface &s, int x, int y);
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 5e2566dc32..824dfec144 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -435,8 +435,9 @@ void ScummEngine_v6::processKeyboard(Common::KeyState lastKeyHit) {
break;
}
- if (VAR_VOICE_MODE != 0xFF)
- VAR(VAR_VOICE_MODE) = _voiceMode;
+ // We need to sync the current sound settings here to make sure that
+ // we actually update the mute state of speech properly.
+ syncSoundSettings();
return;
}
diff --git a/engines/scumm/nut_renderer.cpp b/engines/scumm/nut_renderer.cpp
index 1d5761ef48..d8672c473c 100644
--- a/engines/scumm/nut_renderer.cpp
+++ b/engines/scumm/nut_renderer.cpp
@@ -395,10 +395,6 @@ void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byt
}
void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color) {
- // FIXME: This gets passed a const destination Surface. Intuitively this
- // should never get written to. But sadly it does... For now we simply
- // cast the const qualifier away.
- byte *dst = (byte *)const_cast<void *>(s.getBasePtr(x, y));
const int width = _vm->_2byteWidth;
const int height = MIN(_vm->_2byteHeight, s.h - y);
const byte *src = _vm->get2byteCharPtr(c);
@@ -408,17 +404,50 @@ void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byt
return;
}
- for (int ty = 0; ty < height; ty++) {
- for (int tx = 0; tx < width; tx++) {
- if ((tx & 7) == 0)
- bits = *src++;
- if (x + tx < 0 || x + tx >= s.w || y + ty < 0)
- continue;
- if (bits & revBitMask(tx % 8)) {
- dst[tx] = color;
+ enum ShadowMode {
+ kNone,
+ kKoreanV8ShadowMode
+ };
+
+ ShadowMode shadowMode = kNone;
+
+ if (_vm->_language == Common::KO_KOR && _vm->_game.version == 8) {
+ shadowMode = kKoreanV8ShadowMode;
+ }
+
+ int shadowOffsetXTable[4] = {-1, 0, 1, 0};
+ int shadowOffsetYTable[4] = {0, 1, 0, 0};
+ int shadowOffsetColorTable[4] = {0, 0, 0, color};
+
+ int shadowIdx = 3;
+ if (shadowMode == kKoreanV8ShadowMode)
+ shadowIdx = 0;
+
+ const byte *origSrc = src;
+
+ for (; shadowIdx < 4; shadowIdx++) {
+ int offX = x + shadowOffsetXTable[shadowIdx];
+ int offY = y + shadowOffsetYTable[shadowIdx];
+ byte drawColor = shadowOffsetColorTable[shadowIdx];
+
+ // FIXME: This gets passed a const destination Surface. Intuitively this
+ // should never get written to. But sadly it does... For now we simply
+ // cast the const qualifier away.
+ byte *dst = (byte *)const_cast<void *>(s.getBasePtr(offX, offY));
+ src = origSrc;
+
+ for (int ty = 0; ty < height; ty++) {
+ for (int tx = 0; tx < width; tx++) {
+ if ((tx & 7) == 0)
+ bits = *src++;
+ if (offX + tx < 0 || offX + tx >= s.w || offY + ty < 0)
+ continue;
+ if (bits & revBitMask(tx % 8)) {
+ dst[tx] = drawColor;
+ }
}
+ dst += s.pitch;
}
- dst += s.pitch;
}
}
diff --git a/engines/scumm/smush/smush_font.cpp b/engines/scumm/smush/smush_font.cpp
index 4c04901b42..e2f75a6862 100644
--- a/engines/scumm/smush/smush_font.cpp
+++ b/engines/scumm/smush/smush_font.cpp
@@ -115,9 +115,7 @@ int SmushFont::drawChar(byte *buffer, int dst_width, int x, int y, byte chr) {
int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) {
int w = _vm->_2byteWidth;
int h = _vm->_2byteHeight;
-
- byte *src = _vm->get2byteCharPtr(idx);
- byte *dst = buffer + dst_width * (y + (_vm->_game.id == GID_CMI ? 7 : (_vm->_game.id == GID_DIG ? 2 : 0))) + x;
+ const byte *src = _vm->get2byteCharPtr(idx);
byte bits = 0;
char color = (_color != -1) ? _color : 1;
@@ -128,18 +126,60 @@ int SmushFont::draw2byte(byte *buffer, int dst_width, int x, int y, int idx) {
if (_vm->_game.id == GID_FT)
color = 1;
- for (int j = 0; j < h; j++) {
- for (int i = 0; i < w; i++) {
- if ((i % 8) == 0)
- bits = *src++;
- if (bits & revBitMask(i % 8)) {
- dst[i + 1] = 0;
- dst[dst_width + i] = 0;
- dst[dst_width + i + 1] = 0;
- dst[i] = color;
+ enum ShadowMode {
+ kNone,
+ kNormalShadowMode,
+ kKoreanV7ShadowMode,
+ kKoreanV8ShadowMode
+ };
+
+ ShadowMode shadowMode = kNone;
+
+ if (_vm->_language == Common::KO_KOR) {
+ if (_vm->_game.version == 8)
+ shadowMode = kKoreanV8ShadowMode;
+ else
+ shadowMode = kKoreanV7ShadowMode;
+ }
+
+ int shadowOffsetXTable[4] = {-1, 0, 1, 0};
+ int shadowOffsetYTable[4] = {0, 1, 0, 0};
+ int shadowOffsetColorTable[4] = {0, 0, 0, color};
+
+ int shadowIdx = 3;
+ if (shadowMode == kKoreanV8ShadowMode)
+ shadowIdx = 0;
+ else if (shadowMode == kKoreanV7ShadowMode)
+ shadowIdx = 2;
+
+ const byte *origSrc = src;
+
+ for (; shadowIdx < 4; shadowIdx++) {
+ int offX = x + shadowOffsetXTable[shadowIdx];
+ int offY = y + shadowOffsetYTable[shadowIdx];
+ byte drawColor = shadowOffsetColorTable[shadowIdx];
+
+ src = origSrc;
+
+ byte *dst = buffer + dst_width * (offY + (_vm->_game.id == GID_CMI ? 7 : (_vm->_game.id == GID_DIG ? 2 : 0))) + offX;
+
+ for (int j = 0; j < h; j++) {
+ for (int i = 0; i < w; i++) {
+ if (offX + i < 0)
+ continue;
+ if ((i % 8) == 0)
+ bits = *src++;
+ if (bits & revBitMask(i % 8)) {
+ if (shadowMode == kNormalShadowMode) {
+ dst[i + 1] = 0;
+ dst[dst_width + i] = 0;
+ dst[dst_width + i + 1] = 0;
+ }
+ dst[i] = drawColor;
+ }
}
+ dst += dst_width;
}
- dst += dst_width;
}
return w + 1;
}
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index 7f045517bc..cb428d1c15 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -658,7 +658,11 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
_vm->_imuseDigital->startVoice(kTalkSoundID, input);
#endif
} else {
- _mixer->playStream(Audio::Mixer::kSpeechSoundType, handle, input, id);
+ if (mode == 1) {
+ _mixer->playStream(Audio::Mixer::kSFXSoundType, handle, input, id);
+ } else {
+ _mixer->playStream(Audio::Mixer::kSpeechSoundType, handle, input, id);
+ }
}
}
}
@@ -847,9 +851,6 @@ void Sound::soundKludge(int *list, int num) {
}
void Sound::talkSound(uint32 a, uint32 b, int mode, int channel) {
- if (_vm->_game.version >= 5 && ConfMan.getBool("speech_mute"))
- return;
-
if (mode == 1) {
_talk_sound_a1 = a;
_talk_sound_b1 = b;
diff --git a/engines/toltecs/detection.cpp b/engines/toltecs/detection.cpp
index b6c7ad3d2b..e8f08bcc61 100644
--- a/engines/toltecs/detection.cpp
+++ b/engines/toltecs/detection.cpp
@@ -86,6 +86,20 @@ static const ToltecsGameDescription gameDescriptions[] = {
},
{
+ // 3 Skulls of the Toltecs PIRATE CD-RIP version (no audio)
+ // == DO NOT RE-ADD ==
+ {
+ "toltecs",
+ 0,
+ AD_ENTRY1s("WESTERN", "56d0da91ec3db8ac869594357584e851", 104804435),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_PIRATED,
+ GUIO1(GUIO_NONE)
+ },
+ },
+
+ {
// 3 Skulls of the Toltecs Russian version
{
"toltecs",
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index 14e7d104d2..2f5051c157 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -2037,23 +2037,19 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
}
}
- int32 myId = 0;
char *myLine;
- if (dialogid < 1000) {
+ if (dialogid < 1000)
myLine = _roomTexts->getText(dialogid);
- myId = dialogid;
- } else {
+ else
myLine = _genericTexts->getText(dialogid - 1000);
- myId = dialogid - 1000;
- }
if (!myLine)
return 0;
bool oldMouseHidden = _gameState->_mouseHidden;
- if (blocking) {
+ if (blocking)
_gameState->_mouseHidden = true;
- }
+
// get what is before the string
int a = READ_LE_UINT16(myLine - 2);
@@ -2090,10 +2086,8 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
while ((waitChar->getAnimFlag() & 0x10) == 0x10 && !_shouldQuit)
doFrame();
}
- } else {
- if (_audioManager->voiceStillPlaying())
- _audioManager->stopCurrentVoice();
- }
+ } else if (_audioManager->voiceStillPlaying())
+ _audioManager->stopCurrentVoice();
for (int32 i = 0; i < numParticipants - 1; i++) {
// listener
@@ -2133,10 +2127,10 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
getTextPosition(talkerId, &_currentTextLineX, &_currentTextLineY);
if (dialogid < 1000) {
- myId = _roomTexts->getId(dialogid);
+ int myId = _roomTexts->getId(dialogid);
_audioManager->playVoice(myId, false);
} else {
- myId = _genericTexts->getId(dialogid - 1000);
+ int myId = _genericTexts->getId(dialogid - 1000);
_audioManager->playVoice(myId, true);
}
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index e854378ae4..517278e155 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -155,7 +155,7 @@ bool ActionEnableControl::execute(ZVision *engine) {
ActionMusic::ActionMusic(const Common::String &line) : _volume(255) {
uint type;
- char fileNameBuffer[25];
+ char fileNameBuffer[26];
uint loop;
uint volume = 255;
@@ -211,7 +211,7 @@ bool ActionMusic::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionPreloadAnimation::ActionPreloadAnimation(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
// The two %*u are always 0 and dont seem to have a use
sscanf(line.c_str(), "%*[^:]:%*[^:]:%u(%25s %*u %*u %u %u)", &_key, fileName, &_mask, &_framerate);
@@ -238,7 +238,7 @@ bool ActionPreloadAnimation::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionPlayAnimation::ActionPlayAnimation(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
// The two %*u are always 0 and dont seem to have a use
sscanf(line.c_str(),
@@ -312,7 +312,7 @@ bool ActionRandom::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionSetPartialScreen::ActionSetPartialScreen(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
uint color;
sscanf(line.c_str(), "%*[^(](%u %u %25s %*u %u)", &_x, &_y, fileName, &color);
@@ -342,7 +342,7 @@ bool ActionSetPartialScreen::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionSetScreen::ActionSetScreen(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
sscanf(line.c_str(), "%*[^(](%25[^)])", fileName);
_fileName = Common::String(fileName);
@@ -360,7 +360,7 @@ bool ActionSetScreen::execute(ZVision *engine) {
//////////////////////////////////////////////////////////////////////////////
ActionStreamVideo::ActionStreamVideo(const Common::String &line) {
- char fileName[25];
+ char fileName[26];
uint skippable;
sscanf(line.c_str(), "%*[^(](%25s %u %u %u %u %u %u)", fileName, &_x1, &_y1, &_x2, &_y2, &_flags, &skippable);
diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp
index 5cf5086691..a35548d02e 100644
--- a/engines/zvision/scripting/controls/input_control.cpp
+++ b/engines/zvision/scripting/controls/input_control.cpp
@@ -75,7 +75,7 @@ InputControl::InputControl(ZVision *engine, uint32 key, Common::SeekableReadStre
} else if (line.matchString("*next_tabstop*", true)) {
sscanf(line.c_str(), "%*[^(](%u)", &_nextTabstop);
} else if (line.matchString("*cursor_animation*", true)) {
- char fileName[25];
+ char fileName[26];
sscanf(line.c_str(), "%*[^(](%25s %*u)", fileName);
diff --git a/test/common/rendermode.h b/test/common/rendermode.h
index e5e277f16b..b96ae243a5 100644
--- a/test/common/rendermode.h
+++ b/test/common/rendermode.h
@@ -49,7 +49,6 @@ class RenderModeTestSuite : public CxxTest::TestSuite {
* Notably, the output should not be in mixed case.
*/
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("FMTOWNS")), "fmtowns", 7);
- TS_ASSERT_DIFFERS(Common::getRenderModeCode(Common::parseRenderMode("FMTOWNS")), "fmtowns");
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("CGA")), "cga", 3);
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("vga")), "vga", 3);
TS_ASSERT_SAME_DATA(Common::getRenderModeCode(Common::parseRenderMode("Ega")), "ega", 3);