aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorMatthew Hoops2012-03-20 14:18:57 -0400
committerMatthew Hoops2012-03-20 14:49:16 -0400
commit71756bdf4eae5ba9cc3f329b85e894f04640aaef (patch)
tree40d464262da107ab5eed82f198685209161ebac1 /engines/sci
parent03eba05b09e5c9e5a351f8111185934b92a3fed3 (diff)
parent3c3576a224b92c703b4e8ea20008ac8a069980dd (diff)
downloadscummvm-rg350-71756bdf4eae5ba9cc3f329b85e894f04640aaef.tar.gz
scummvm-rg350-71756bdf4eae5ba9cc3f329b85e894f04640aaef.tar.bz2
scummvm-rg350-71756bdf4eae5ba9cc3f329b85e894f04640aaef.zip
Merge remote branch 'upstream/master' into pegasus
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/console.cpp73
-rw-r--r--engines/sci/detection.cpp18
-rw-r--r--engines/sci/detection_tables.h9
-rw-r--r--engines/sci/engine/features.cpp9
-rw-r--r--engines/sci/engine/kernel_tables.h6
-rw-r--r--engines/sci/engine/kfile.cpp11
-rw-r--r--engines/sci/engine/kgraphics.cpp112
-rw-r--r--engines/sci/engine/klists.cpp18
-rw-r--r--engines/sci/engine/kmenu.cpp2
-rw-r--r--engines/sci/engine/kpathing.cpp1
-rw-r--r--engines/sci/engine/kscripts.cpp10
-rw-r--r--engines/sci/engine/kstring.cpp24
-rw-r--r--engines/sci/engine/message.cpp2
-rw-r--r--engines/sci/engine/savegame.cpp22
-rw-r--r--engines/sci/engine/script_patches.cpp62
-rw-r--r--engines/sci/engine/scriptdebug.cpp2
-rw-r--r--engines/sci/engine/seg_manager.cpp2
-rw-r--r--engines/sci/engine/segment.cpp7
-rw-r--r--engines/sci/engine/segment.h2
-rw-r--r--engines/sci/engine/vm.cpp3
-rw-r--r--engines/sci/engine/workarounds.cpp2
-rw-r--r--engines/sci/graphics/controls16.cpp2
-rw-r--r--engines/sci/graphics/cursor.cpp53
-rw-r--r--engines/sci/graphics/cursor.h15
-rw-r--r--engines/sci/graphics/frameout.cpp54
-rw-r--r--engines/sci/graphics/frameout.h1
-rw-r--r--engines/sci/graphics/maciconbar.cpp18
-rw-r--r--engines/sci/graphics/maciconbar.h2
-rw-r--r--engines/sci/graphics/menu.cpp4
-rw-r--r--engines/sci/graphics/paint16.cpp2
-rw-r--r--engines/sci/graphics/screen.cpp8
-rw-r--r--engines/sci/graphics/text16.cpp2
-rw-r--r--engines/sci/graphics/text32.cpp24
-rw-r--r--engines/sci/graphics/text32.h5
-rw-r--r--engines/sci/graphics/transitions.cpp14
-rw-r--r--engines/sci/parser/said.cpp2
-rw-r--r--engines/sci/parser/vocabulary.cpp2
-rw-r--r--engines/sci/resource.cpp24
-rw-r--r--engines/sci/resource.h2
-rw-r--r--engines/sci/resource_audio.cpp27
-rw-r--r--engines/sci/sci.cpp1
-rw-r--r--engines/sci/sound/drivers/amigamac.cpp6
-rw-r--r--engines/sci/sound/music.cpp10
-rw-r--r--engines/sci/sound/music.h7
-rw-r--r--engines/sci/sound/soundcmd.cpp30
-rw-r--r--engines/sci/sound/soundcmd.h4
46 files changed, 459 insertions, 257 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index 571d2f834b..9607a8e66d 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -860,14 +860,14 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
return true;
}
- Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeScript);
- Common::sort(resources->begin(), resources->end());
- Common::List<ResourceId>::iterator itr = resources->begin();
+ Common::List<ResourceId> resources = _engine->getResMan()->listResources(kResourceTypeScript);
+ Common::sort(resources.begin(), resources.end());
- DebugPrintf("%d SCI1.1-SCI3 scripts found, performing sanity checks...\n", resources->size());
+ DebugPrintf("%d SCI1.1-SCI3 scripts found, performing sanity checks...\n", resources.size());
Resource *script, *heap;
- while (itr != resources->end()) {
+ Common::List<ResourceId>::iterator itr;
+ for (itr = resources.begin(); itr != resources.end(); ++itr) {
script = _engine->getResMan()->findResource(*itr, false);
if (!script)
DebugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber());
@@ -885,12 +885,9 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
DebugPrintf("Error: script %d is larger than 64KB (%d bytes)\n",
itr->getNumber(), script->size);
}
-
- ++itr;
}
DebugPrintf("SCI1.1-SCI2.1 script check finished\n");
- delete resources;
return true;
}
@@ -914,9 +911,8 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion, 0);
parser->setMidiDriver(player);
- Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeSound);
- Common::sort(resources->begin(), resources->end());
- Common::List<ResourceId>::iterator itr = resources->begin();
+ Common::List<ResourceId> resources = _engine->getResMan()->listResources(kResourceTypeSound);
+ Common::sort(resources.begin(), resources.end());
int instruments[128];
bool instrumentsSongs[128][1000];
@@ -928,26 +924,21 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
instrumentsSongs[i][j] = false;
if (songNumber == -1) {
- DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources->size());
+ DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources.size());
DebugPrintf("Instruments:\n");
DebugPrintf("============\n");
}
- SoundResource *sound;
-
- while (itr != resources->end()) {
- if (songNumber >= 0 && itr->getNumber() != songNumber) {
- ++itr;
+ Common::List<ResourceId>::iterator itr;
+ for (itr = resources.begin(); itr != resources.end(); ++itr) {
+ if (songNumber >= 0 && itr->getNumber() != songNumber)
continue;
- }
- sound = new SoundResource(itr->getNumber(), _engine->getResMan(), doSoundVersion);
- int channelFilterMask = sound->getChannelFilterMask(player->getPlayId(), player->hasRhythmChannel());
- SoundResource::Track *track = sound->getTrackByType(player->getPlayId());
+ SoundResource sound(itr->getNumber(), _engine->getResMan(), doSoundVersion);
+ int channelFilterMask = sound.getChannelFilterMask(player->getPlayId(), player->hasRhythmChannel());
+ SoundResource::Track *track = sound.getTrackByType(player->getPlayId());
if (track->digitalChannelNr != -1) {
// Skip digitized sound effects
- delete sound;
- ++itr;
continue;
}
@@ -1027,9 +1018,6 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
} while (!endOfTrack);
DebugPrintf("\n");
-
- delete sound;
- ++itr;
}
delete parser;
@@ -1069,7 +1057,6 @@ bool Console::cmdShowInstruments(int argc, const char **argv) {
DebugPrintf("\n\n");
}
- delete resources;
return true;
}
@@ -1132,12 +1119,12 @@ bool Console::cmdList(int argc, const char **argv) {
number = atoi(argv[2]);
}
- Common::List<ResourceId> *resources = _engine->getResMan()->listResources(res, number);
- Common::sort(resources->begin(), resources->end());
- Common::List<ResourceId>::iterator itr = resources->begin();
+ Common::List<ResourceId> resources = _engine->getResMan()->listResources(res, number);
+ Common::sort(resources.begin(), resources.end());
int cnt = 0;
- while (itr != resources->end()) {
+ Common::List<ResourceId>::iterator itr;
+ for (itr = resources.begin(); itr != resources.end(); ++itr) {
if (number == -1) {
DebugPrintf("%8i", itr->getNumber());
if (++cnt % 10 == 0)
@@ -1149,10 +1136,8 @@ bool Console::cmdList(int argc, const char **argv) {
if (++cnt % 4 == 0)
DebugPrintf("\n");
}
- ++itr;
}
DebugPrintf("\n");
- delete resources;
}
return true;
@@ -1448,7 +1433,7 @@ bool Console::cmdSaid(int argc, const char **argv) {
_engine->getVocabulary()->dumpParseTree();
_engine->getVocabulary()->parserIsValid = true;
- int ret = said((byte*)spec, true);
+ int ret = said((byte *)spec, true);
DebugPrintf("kSaid: %s\n", (ret == SAID_NO_MATCH ? "No match" : "Match"));
}
@@ -1620,7 +1605,7 @@ bool Console::cmdWindowList(int argc, const char **argv) {
bool Console::cmdSavedBits(int argc, const char **argv) {
SegManager *segman = _engine->_gamestate->_segMan;
SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK);
- HunkTable* hunks = (HunkTable*)segman->getSegmentObj(id);
+ HunkTable* hunks = (HunkTable *)segman->getSegmentObj(id);
if (!hunks) {
DebugPrintf("No hunk segment found.\n");
return true;
@@ -1632,7 +1617,7 @@ bool Console::cmdSavedBits(int argc, const char **argv) {
uint16 offset = entries[i].offset;
const Hunk& h = hunks->_table[offset];
if (strcmp(h.type, "SaveBits()") == 0) {
- byte* memoryPtr = (byte*)h.mem;
+ byte* memoryPtr = (byte *)h.mem;
if (memoryPtr) {
DebugPrintf("%04x:%04x:", PRINT_REG(entries[i]));
@@ -1686,7 +1671,7 @@ bool Console::cmdShowSavedBits(int argc, const char **argv) {
SegManager *segman = _engine->_gamestate->_segMan;
SegmentId id = segman->findSegmentByType(SEG_TYPE_HUNK);
- HunkTable* hunks = (HunkTable*)segman->getSegmentObj(id);
+ HunkTable* hunks = (HunkTable *)segman->getSegmentObj(id);
if (!hunks) {
DebugPrintf("No hunk segment found.\n");
return true;
@@ -2915,12 +2900,11 @@ bool Console::cmdDisassembleAddress(int argc, const char **argv) {
}
void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
- Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeScript);
- Common::sort(resources->begin(), resources->end());
- Common::List<ResourceId>::iterator itr = resources->begin();
+ Common::List<ResourceId> resources = _engine->getResMan()->listResources(kResourceTypeScript);
+ Common::sort(resources.begin(), resources.end());
if (showFoundScripts)
- DebugPrintf("%d scripts found, dissassembling...\n", resources->size());
+ DebugPrintf("%d scripts found, dissassembling...\n", resources.size());
int scriptSegment;
Script *script;
@@ -2928,13 +2912,13 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
// manager won't be affected by loading and unloading scripts here.
SegManager *customSegMan = new SegManager(_engine->getResMan());
- while (itr != resources->end()) {
+ Common::List<ResourceId>::iterator itr;
+ for (itr = resources.begin(); itr != resources.end(); ++itr) {
// Ignore specific leftover scripts, which require other non-existing scripts
if ((_engine->getGameId() == GID_HOYLE3 && itr->getNumber() == 995) ||
(_engine->getGameId() == GID_KQ5 && itr->getNumber() == 980) ||
(_engine->getGameId() == GID_SLATER && itr->getNumber() == 947) ||
(_engine->getGameId() == GID_MOTHERGOOSE256 && itr->getNumber() == 980)) {
- itr++;
continue;
}
@@ -2993,12 +2977,9 @@ void Console::printKernelCallsFound(int kernelFuncNum, bool showFoundScripts) {
} // for (it = script->_objects.begin(); it != end; ++it)
customSegMan->uninstantiateScript(itr->getNumber());
- ++itr;
}
delete customSegMan;
-
- delete resources;
}
bool Console::cmdFindKernelFunctionCall(int argc, const char **argv) {
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index 80f45b4325..c43849056b 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -303,29 +303,29 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R
if (sierraId == "fp" || sierraId == "gk" || sierraId == "pq4")
demoThreshold = 150;
- Common::ScopedPtr<Common::List<ResourceId> > resources(resMan.listResources(kResourceTypeScript, -1));
- if (resources->size() < demoThreshold) {
+ Common::List<ResourceId> resources = resMan.listResources(kResourceTypeScript, -1);
+ if (resources.size() < demoThreshold) {
*gameFlags |= ADGF_DEMO;
// Crazy Nick's Picks
- if (sierraId == "lsl1" && resources->size() == 34)
+ if (sierraId == "lsl1" && resources.size() == 34)
return "cnick-lsl";
- if (sierraId == "sq4" && resources->size() == 34)
+ if (sierraId == "sq4" && resources.size() == 34)
return "cnick-sq";
- if (sierraId == "hoyle3" && resources->size() == 42)
+ if (sierraId == "hoyle3" && resources.size() == 42)
return "cnick-kq";
- if (sierraId == "rh budget" && resources->size() == 39)
+ if (sierraId == "rh budget" && resources.size() == 39)
return "cnick-longbow";
// TODO: cnick-laurabow (the name of the game object contains junk)
// Handle Astrochicken 1 (SQ3) and 2 (SQ4)
- if (sierraId == "sq3" && resources->size() == 20)
+ if (sierraId == "sq3" && resources.size() == 20)
return "astrochicken";
if (sierraId == "sq4")
return "msastrochicken";
}
- if (sierraId == "torin" && resources->size() == 226) // Torin's Passage demo
+ if (sierraId == "torin" && resources.size() == 226) // Torin's Passage demo
*gameFlags |= ADGF_DEMO;
for (const OldNewIdTableEntry *cur = s_oldNewTable; cur->oldId[0]; ++cur) {
@@ -350,7 +350,7 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R
return "qfg4";
// qfg4 demo has less than 50 scripts
- if (resources->size() < 50)
+ if (resources.size() < 50)
return "qfg4";
// Otherwise it's qfg3
diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h
index 63eda1c348..2047f58c8b 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -1421,6 +1421,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) },
+ // King's Quest 6 - French DOS Floppy (supplied by misterhands in bug #3503425)
+ // SCI interpreter version ???
+ {"kq6", "", {
+ {"resource.map", 0, "a362063318eebe7d6423b1d9dc6213e1", 8703},
+ {"resource.000", 0, "f2b7f753992c56a0c7a08d6a5077c895", 7863324},
+ {"resource.msg", 0, "adc2aa8adbdcc97507d44a6f492fbd77", 265194},
+ AD_LISTEND},
+ Common::FR_FRA, Common::kPlatformPC, 0, GUIO1(GUIO_NOSPEECH) },
+
// King's Quest 6 - German DOS Floppy (supplied by markcoolio in bug report #2727156)
// SCI interpreter version 1.001.054
{"kq6", "", {
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index a5c1b970f1..b3cfee873c 100644
--- a/engines/sci/engine/features.cpp
+++ b/engines/sci/engine/features.cpp
@@ -430,19 +430,16 @@ SciVersion GameFeatures::detectMessageFunctionType() {
return _messageFunctionType;
}
- Common::List<ResourceId> *resources = g_sci->getResMan()->listResources(kResourceTypeMessage, -1);
-
- if (resources->empty()) {
- delete resources;
+ Common::List<ResourceId> resources = g_sci->getResMan()->listResources(kResourceTypeMessage, -1);
+ if (resources.empty()) {
// No messages found, so this doesn't really matter anyway...
_messageFunctionType = SCI_VERSION_1_1;
return _messageFunctionType;
}
- Resource *res = g_sci->getResMan()->findResource(*resources->begin(), false);
+ Resource *res = g_sci->getResMan()->findResource(*resources.begin(), false);
assert(res);
- delete resources;
// Only v2 Message resources use the kGetMessage kernel function.
// v3-v5 use the kMessage kernel function.
diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h
index fe0c9fc2ef..622511c906 100644
--- a/engines/sci/engine/kernel_tables.h
+++ b/engines/sci/engine/kernel_tables.h
@@ -610,6 +610,12 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_DUMMY(DeletePic), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_DUMMY(GetSierraProfileString), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ // Unused / debug functions in the in-between SCI2.1 interpreters
+ { MAP_DUMMY(PreloadResource), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_DUMMY(CheckCDisc), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_DUMMY(GetSaveCDisc), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_DUMMY(TestPoly), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+
// SCI2.1 unmapped functions - TODO!
// MovePlaneItems - used by SQ6 to scroll through the inventory via the up/down buttons
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index ce903626e7..312497720a 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -24,6 +24,7 @@
#include "common/config-manager.h"
#include "common/debug-channels.h"
#include "common/file.h"
+#include "common/macresman.h"
#include "common/str.h"
#include "common/savefile.h"
#include "common/system.h"
@@ -823,7 +824,7 @@ reg_t kFileIOWriteRaw(EngineState *s, int argc, reg_t *argv) {
int size = argv[2].toUint16();
char *buf = new char[size];
bool success = false;
- s->_segMan->memcpy((byte*)buf, argv[1], size);
+ s->_segMan->memcpy((byte *)buf, argv[1], size);
debugC(kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size);
FileHandle *f = getFileFromHandle(s, handle);
@@ -1080,6 +1081,14 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) {
delete outFile;
}
+ // Special case for KQ6 Mac: The game checks for two video files to see
+ // if they exist before it plays them. Since we support multiple naming
+ // schemes for resource fork files, we also need to support that here in
+ // case someone has a "HalfDome.bin" file, etc.
+ if (!exists && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformMacintosh &&
+ (name == "HalfDome" || name == "Kq6Movie"))
+ exists = Common::MacResManager::exists(name);
+
debugC(kDebugLevelFile, "kFileIO(fileExists) %s -> %d", name.c_str(), exists);
return make_reg(0, exists);
}
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 76c6778f0a..caae562d67 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -25,6 +25,7 @@
#include "engines/util.h"
#include "graphics/cursorman.h"
#include "graphics/surface.h"
+#include "graphics/palette.h" // temporary, for the fadeIn()/fadeOut() functions below
#include "gui/message.h"
@@ -58,11 +59,13 @@
namespace Sci {
static int16 adjustGraphColor(int16 color) {
- // WORKAROUND: SCI1 EGA and Amiga games can set invalid colors (above 0 - 15).
- // Colors above 15 are all white in SCI1 EGA games, which is why this was never
- // observed. We clip them all to (0, 15) instead, as colors above 15 are used
- // for the undithering algorithm in EGA games - bug #3048908.
- if (getSciVersion() >= SCI_VERSION_1_EARLY && g_sci->getResMan()->getViewType() == kViewEga)
+ // WORKAROUND: EGA and Amiga games can set invalid colors (above 0 - 15).
+ // It seems only the lower nibble was used in these games.
+ // bug #3048908, #3486899.
+ // Confirmed in EGA games KQ4(late), QFG1(ega), LB1 that
+ // at least FillBox (only one of the functions using adjustGraphColor)
+ // behaves like this.
+ if (g_sci->getResMan()->getViewType() == kViewEga)
return color & 0x0F; // 0 - 15
else
return color;
@@ -1212,7 +1215,8 @@ reg_t kRemapColors(EngineState *s, int argc, reg_t *argv) {
switch (operation) {
case 0: { // Set remapping to base. 0 turns remapping off.
int16 base = (argc >= 2) ? argv[1].toSint16() : 0;
- warning("kRemapColors: Set remapping to base %d", base);
+ if (base != 0) // 0 is the default behavior when changing rooms in GK1, thus silencing the warning
+ warning("kRemapColors: Set remapping to base %d", base);
}
break;
case 1: { // unknown
@@ -1440,6 +1444,46 @@ reg_t kWinHelp(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+// Taken from the SCI16 GfxTransitions class
+static void fadeOut() {
+ byte oldPalette[3 * 256], workPalette[3 * 256];
+ int16 stepNr, colorNr;
+ // Sierra did not fade in/out color 255 for sci1.1, but they used it in
+ // several pictures (e.g. qfg3 demo/intro), so the fading looked weird
+ int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254;
+
+ g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256);
+
+ for (stepNr = 100; stepNr >= 0; stepNr -= 10) {
+ for (colorNr = 1; colorNr <= tillColorNr; colorNr++) {
+ if (g_sci->_gfxPalette->colorIsFromMacClut(colorNr)) {
+ workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3];
+ workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1];
+ workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2];
+ } else {
+ workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3] * stepNr / 100;
+ workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1] * stepNr / 100;
+ workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100;
+ }
+ }
+ g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr);
+ g_sci->getEngineState()->wait(2);
+ }
+}
+
+// Taken from the SCI16 GfxTransitions class
+static void fadeIn() {
+ int16 stepNr;
+ // Sierra did not fade in/out color 255 for sci1.1, but they used it in
+ // several pictures (e.g. qfg3 demo/intro), so the fading looked weird
+ int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254;
+
+ for (stepNr = 0; stepNr <= 100; stepNr += 10) {
+ g_sci->_gfxPalette->kernelSetIntensity(1, tillColorNr + 1, stepNr, true);
+ g_sci->getEngineState()->wait(2);
+ }
+}
+
/**
* Used for scene transitions, replacing (but reusing parts of) the old
* transition code.
@@ -1450,31 +1494,65 @@ reg_t kSetShowStyle(EngineState *s, int argc, reg_t *argv) {
// tables inside graphics/transitions.cpp
uint16 showStyle = argv[0].toUint16(); // 0 - 15
reg_t planeObj = argv[1]; // the affected plane
- //argv[2] // seconds that the transition lasts
- //argv[3] // back color to be used(?)
- //int16 priority = argv[4].toSint16();
- //argv[5] // boolean, animate or not while the transition lasts
- //argv[6] // refFrame
+ uint16 seconds = argv[2].toUint16(); // seconds that the transition lasts
+ uint16 backColor = argv[3].toUint16(); // target back color(?). When fading out, it's 0x0000. When fading in, it's 0xffff
+ int16 priority = argv[4].toSint16(); // always 0xc8 (200) when fading in/out
+ uint16 animate = argv[5].toUint16(); // boolean, animate or not while the transition lasts
+ uint16 refFrame = argv[6].toUint16(); // refFrame, always 0 when fading in/out
+ int16 divisions;
// If the game has the pFadeArray selector, another parameter is used here,
// before the optional last parameter
- /*bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0;
+ bool hasFadeArray = g_sci->getKernel()->findSelector("pFadeArray") > 0;
if (hasFadeArray) {
// argv[7]
- //int16 unk7 = (argc >= 9) ? argv[8].toSint16() : 0; // divisions (transition steps?)
+ divisions = (argc >= 9) ? argv[8].toSint16() : -1; // divisions (transition steps?)
} else {
- //int16 unk7 = (argc >= 8) ? argv[7].toSint16() : 0; // divisions (transition steps?)
- }*/
+ divisions = (argc >= 8) ? argv[7].toSint16() : -1; // divisions (transition steps?)
+ }
if (showStyle > 15) {
warning("kSetShowStyle: Illegal style %d for plane %04x:%04x", showStyle, PRINT_REG(planeObj));
return s->r_acc;
}
+ // TODO: Proper implementation. This is a very basic version. I'm not even
+ // sure if the rest of the styles will work with this mechanism.
+
+ // Check if the passed parameters are the ones we expect
+ if (showStyle == 13 || showStyle == 14) { // fade out / fade in
+ if (seconds != 1)
+ warning("kSetShowStyle(fade): seconds isn't 1, it's %d", seconds);
+ if (backColor != 0 && backColor != 0xFFFF)
+ warning("kSetShowStyle(fade): backColor isn't 0 or 0xFFFF, it's %d", backColor);
+ if (priority != 200)
+ warning("kSetShowStyle(fade): priority isn't 200, it's %d", priority);
+ if (animate != 0)
+ warning("kSetShowStyle(fade): animate isn't 0, it's %d", animate);
+ if (refFrame != 0)
+ warning("kSetShowStyle(fade): refFrame isn't 0, it's %d", refFrame);
+ if (divisions >= 0 && divisions != 20)
+ warning("kSetShowStyle(fade): divisions isn't 20, it's %d", divisions);
+ }
+
// TODO: Check if the plane is in the list of planes to draw
- // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now
- kStub(s, argc, argv);
+ switch (showStyle) {
+ //case 0: // no transition, perhaps? (like in the previous SCI versions)
+ case 13: // fade out
+ // TODO: Temporary implementation, which ignores all additional parameters
+ fadeOut();
+ break;
+ case 14: // fade in
+ // TODO: Temporary implementation, which ignores all additional parameters
+ g_sci->_gfxFrameout->kernelFrameout(); // draw new scene before fading in
+ fadeIn();
+ break;
+ default:
+ // TODO: This is all a stub/skeleton, thus we're invoking kStub() for now
+ kStub(s, argc, argv);
+ break;
+ }
return s->r_acc;
}
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index 83e59c9c20..2a33df26bc 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -753,7 +753,6 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) {
reg_t arrayHandle = argv[1];
SciArray<reg_t> *array1 = s->_segMan->lookupArray(argv[1]);
- //SciArray<reg_t> *array1 = !argv[1].isNull() ? s->_segMan->lookupArray(argv[1]) : s->_segMan->allocateArray(&arrayHandle);
SciArray<reg_t> *array2 = s->_segMan->lookupArray(argv[3]);
uint32 index1 = argv[2].toUint16();
uint32 index2 = argv[4].toUint16();
@@ -790,21 +789,8 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) {
#endif
return NULL_REG;
}
- SegmentType sourceType = s->_segMan->getSegmentObj(argv[1].segment)->getType();
- if (sourceType == SEG_TYPE_SCRIPT) {
- // A technique used in later SCI2.1 and SCI3 games: the contents of a script
- // are loaded in an array (well, actually a string).
- Script *scr = s->_segMan->getScript(argv[1].segment);
- reg_t stringHandle;
-
- SciString *dupString = s->_segMan->allocateString(&stringHandle);
- dupString->setSize(scr->getBufSize());
- dupString->fromString(Common::String((const char *)scr->getBuf()));
-
- return stringHandle;
- } else if (sourceType != SEG_TYPE_ARRAY && sourceType != SEG_TYPE_SCRIPT) {
- error("kArray(Dup): Request to duplicate a segment which isn't an array or a script");
- }
+ if (s->_segMan->getSegmentObj(argv[1].segment)->getType() != SEG_TYPE_ARRAY)
+ error("kArray(Dup): Request to duplicate a segment which isn't an array");
reg_t arrayHandle;
SciArray<reg_t> *dupArray = s->_segMan->allocateArray(&arrayHandle);
diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp
index 02aa1d3ece..05ba7005d7 100644
--- a/engines/sci/engine/kmenu.cpp
+++ b/engines/sci/engine/kmenu.cpp
@@ -94,7 +94,7 @@ reg_t kDrawMenuBar(EngineState *s, int argc, reg_t *argv) {
reg_t kMenuSelect(EngineState *s, int argc, reg_t *argv) {
reg_t eventObject = argv[0];
- bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : true;
+ bool pauseSound = argc <= 1 || !argv[1].isNull();
return g_sci->_gfxMenu->kernelSelect(eventObject, pauseSound);
}
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 375aeaa06b..089b325a7f 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -1545,7 +1545,6 @@ reg_t kAvoidPath(EngineState *s, int argc, reg_t *argv) {
default:
warning("Unknown AvoidPath subfunction %d", argc);
return NULL_REG;
- break;
}
}
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index 93c1fffe3c..9b0e490d7e 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -74,17 +74,13 @@ reg_t kLock(EngineState *s, int argc, reg_t *argv) {
case 0 :
if (id.getNumber() == 0xFFFF) {
// Unlock all resources of the requested type
- Common::List<ResourceId> *resources = g_sci->getResMan()->listResources(type);
- Common::List<ResourceId>::iterator itr = resources->begin();
-
- while (itr != resources->end()) {
+ Common::List<ResourceId> resources = g_sci->getResMan()->listResources(type);
+ Common::List<ResourceId>::iterator itr;
+ for (itr = resources.begin(); itr != resources.end(); ++itr) {
Resource *res = g_sci->getResMan()->testResource(*itr);
if (res->isLocked())
g_sci->getResMan()->unlockResource(res);
- ++itr;
}
-
- delete resources;
} else {
which = g_sci->getResMan()->findResource(id, 0);
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 5ae18c1367..fe8d631497 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -147,7 +147,7 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) {
Common::String source_str = s->_segMan->getString(argv[0]);
const char *source = source_str.c_str();
- while (isspace((unsigned char)*source))
+ while (Common::isSpace(*source))
source++; /* Skip whitespace */
int16 result = 0;
@@ -246,14 +246,14 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
/* int writelength; -- unused atm */
- if (xfer && (isdigit(static_cast<unsigned char>(xfer)) || xfer == '-' || xfer == '=')) {
+ if (xfer && (Common::isDigit(xfer) || xfer == '-' || xfer == '=')) {
char *destp;
if (xfer == '0')
fillchar = '0';
else if (xfer == '=')
align = ALIGN_CENTER;
- else if (isdigit(static_cast<unsigned char>(xfer)) || (xfer == '-'))
+ else if (Common::isDigit(xfer) || (xfer == '-'))
source--; // Go to start of length argument
strLength = strtol(source, &destp, 10);
@@ -745,28 +745,16 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, strcmp(string1.c_str(), string2.c_str()));
}
case 8: { // Dup
- const char *rawString = 0;
- uint32 size = 0;
reg_t stringHandle;
- // We allocate the new string first because if the StringTable needs to
- // grow, our rawString pointer will be invalidated
+
SciString *dupString = s->_segMan->allocateString(&stringHandle);
if (argv[1].segment == s->_segMan->getStringSegmentId()) {
- SciString *string = s->_segMan->lookupString(argv[1]);
- rawString = string->getRawData();
- size = string->getSize();
+ *dupString = *s->_segMan->lookupString(argv[1]);
} else {
- Common::String string = s->_segMan->getString(argv[1]);
- rawString = string.c_str();
- size = string.size() + 1;
+ dupString->fromString(s->_segMan->getString(argv[1]));
}
- dupString->setSize(size);
-
- for (uint32 i = 0; i < size; i++)
- dupString->setValue(i, rawString[i]);
-
return stringHandle;
}
case 9: // Getdata
diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp
index f30f4e923e..cddd01e10c 100644
--- a/engines/sci/engine/message.cpp
+++ b/engines/sci/engine/message.cpp
@@ -345,7 +345,7 @@ bool MessageState::stringLit(Common::String &outStr, const Common::String &inStr
}
bool MessageState::stringStage(Common::String &outstr, const Common::String &inStr, uint &index) {
- // Stage directions of the form (n*), where n is anything but a digit or a lowercase character
+ // Stage directions of the form (n *), where n is anything but a digit or a lowercase character
if (inStr[index] != '(')
return false;
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index f1c7133d01..404bea799d 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -66,7 +66,7 @@ void syncWithSerializer(Common::Serializer &s, T &obj) {
}
// By default, sync using syncWithSerializer, which in turn can easily be overloaded.
-template <typename T>
+template<typename T>
struct DefaultSyncer : Common::BinaryFunction<Common::Serializer, T, void> {
void operator()(Common::Serializer &s, T &obj) const {
//obj.saveLoadWithSerializer(s);
@@ -87,7 +87,7 @@ struct DefaultSyncer : Common::BinaryFunction<Common::Serializer, T, void> {
*
* TODO: Add something like this for lists, queues....
*/
-template <typename T, class Syncer = DefaultSyncer<T> >
+template<typename T, class Syncer = DefaultSyncer<T> >
struct ArraySyncer : Common::BinaryFunction<Common::Serializer, T, void> {
void operator()(Common::Serializer &s, Common::Array<T> &arr) const {
uint len = arr.size();
@@ -113,13 +113,13 @@ void syncArray(Common::Serializer &s, Common::Array<T> &arr) {
}
-template <>
+template<>
void syncWithSerializer(Common::Serializer &s, reg_t &obj) {
s.syncAsUint16LE(obj.segment);
s.syncAsUint16LE(obj.offset);
}
-template <>
+template<>
void syncWithSerializer(Common::Serializer &s, synonym_t &obj) {
s.syncAsUint16LE(obj.replaceant);
s.syncAsUint16LE(obj.replacement);
@@ -247,7 +247,7 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
}
-template <>
+template<>
void syncWithSerializer(Common::Serializer &s, Class &obj) {
s.syncAsSint32LE(obj.script);
syncWithSerializer(s, obj.reg);
@@ -326,14 +326,14 @@ void Object::saveLoadWithSerializer(Common::Serializer &s) {
syncArray<reg_t>(s, _variables);
}
-template <>
+template<>
void syncWithSerializer(Common::Serializer &s, SegmentObjTable<Clone>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
syncWithSerializer<Object>(s, obj);
}
-template <>
+template<>
void syncWithSerializer(Common::Serializer &s, SegmentObjTable<List>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
@@ -341,7 +341,7 @@ void syncWithSerializer(Common::Serializer &s, SegmentObjTable<List>::Entry &obj
syncWithSerializer(s, obj.last);
}
-template <>
+template<>
void syncWithSerializer(Common::Serializer &s, SegmentObjTable<Node>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
@@ -352,7 +352,7 @@ void syncWithSerializer(Common::Serializer &s, SegmentObjTable<Node>::Entry &obj
}
#ifdef ENABLE_SCI32
-template <>
+template<>
void syncWithSerializer(Common::Serializer &s, SegmentObjTable<SciArray<reg_t> >::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
@@ -388,7 +388,7 @@ void syncWithSerializer(Common::Serializer &s, SegmentObjTable<SciArray<reg_t> >
}
}
-template <>
+template<>
void syncWithSerializer(Common::Serializer &s, SegmentObjTable<SciString>::Entry &obj) {
s.syncAsSint32LE(obj.next_free);
@@ -416,7 +416,7 @@ void syncWithSerializer(Common::Serializer &s, SegmentObjTable<SciString>::Entry
}
#endif
-template <typename T>
+template<typename T>
void sync_Table(Common::Serializer &s, T &obj) {
s.syncAsSint32LE(obj.first_free);
s.syncAsSint32LE(obj.entries_used);
diff --git a/engines/sci/engine/script_patches.cpp b/engines/sci/engine/script_patches.cpp
index 7efcb42f4b..187f1ce021 100644
--- a/engines/sci/engine/script_patches.cpp
+++ b/engines/sci/engine/script_patches.cpp
@@ -366,7 +366,7 @@ const uint16 freddypharkasPatchLadderEvent[] = {
// script, description, magic DWORD, adjust
const SciScriptSignature freddypharkasSignatures[] = {
{ 0, "CD: score early disposal", 1, PATCH_MAGICDWORD(0x39, 0x0d, 0x43, 0x75), -3, freddypharkasSignatureScoreDisposal, freddypharkasPatchScoreDisposal },
- { 235, "CD: canister pickup hang", 3, PATCH_MAGICDWORD(0x39, 0x07, 0x39, 0x08), -4, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang },
+ { 235, "CD: canister pickup hang", 3, PATCH_MAGICDWORD(0x39, 0x07, 0x39, 0x08), -4, freddypharkasSignatureCanisterHang, freddypharkasPatchCanisterHang },
{ 320, "ladder event issue", 2, PATCH_MAGICDWORD(0x6d, 0x76, 0x38, 0xf5), -1, freddypharkasSignatureLadderEvent, freddypharkasPatchLadderEvent },
SCI_SIGNATUREENTRY_TERMINATOR
};
@@ -437,8 +437,68 @@ const uint16 gk1PatchDay5PhoneFreeze[] = {
PATCH_END
};
+// Floppy version: Interrogation::dispose() compares an object reference
+// (stored in the view selector) with a number, leading to a crash (this kind
+// of comparison was not used in SCI32). The view selector is used to store
+// both a view number (in some cases), and a view reference (in other cases).
+// In the floppy version, the checks are in the wrong order, so there is a
+// comparison between a number an an object. In the CD version, the checks are
+// in the correct order, thus the comparison is correct, thus we use the code
+// from the CD version in the floppy one.
+const byte gk1SignatureInterrogationBug[] = {
+ 43,
+ 0x65, 0x4c, // aTop 4c
+ 0x67, 0x50, // pTos 50
+ 0x34, 0x10, 0x27, // ldi 2710
+ 0x1e, // gt?
+ 0x31, 0x08, // bnt 08 [05a0]
+ 0x67, 0x50, // pTos 50
+ 0x34, 0x10, 0x27, // ldi 2710
+ 0x04, // sub
+ 0x65, 0x50, // aTop 50
+ 0x63, 0x50, // pToa 50
+ 0x31, 0x15, // bnt 15 [05b9]
+ 0x39, 0x0e, // pushi 0e
+ 0x76, // push0
+ 0x4a, 0x04, 0x00, // send 0004
+ 0xa5, 0x00, // sat 00
+ 0x38, 0x93, 0x00, // pushi 0093
+ 0x76, // push0
+ 0x63, 0x50, // pToa 50
+ 0x4a, 0x04, 0x00, // send 0004
+ 0x85, 0x00, // lat 00
+ 0x65, 0x50, // aTop 50
+ 0
+};
+
+const uint16 gk1PatchInterrogationBug[] = {
+ 0x65, 0x4c, // aTop 4c
+ 0x63, 0x50, // pToa 50
+ 0x31, 0x15, // bnt 15 [05b9]
+ 0x39, 0x0e, // pushi 0e
+ 0x76, // push0
+ 0x4a, 0x04, 0x00, // send 0004
+ 0xa5, 0x00, // sat 00
+ 0x38, 0x93, 0x00, // pushi 0093
+ 0x76, // push0
+ 0x63, 0x50, // pToa 50
+ 0x4a, 0x04, 0x00, // send 0004
+ 0x85, 0x00, // lat 00
+ 0x65, 0x50, // aTop 50
+ 0x67, 0x50, // pTos 50
+ 0x34, 0x10, 0x27, // ldi 2710
+ 0x1e, // gt?
+ 0x31, 0x08, // bnt 08 [05b9]
+ 0x67, 0x50, // pTos 50
+ 0x34, 0x10, 0x27, // ldi 2710
+ 0x04, // sub
+ 0x65, 0x50, // aTop 50
+ PATCH_END
+};
+
// script, description, magic DWORD, adjust
const SciScriptSignature gk1Signatures[] = {
+ { 51, "interrogation bug", 1, PATCH_MAGICDWORD(0x65, 0x4c, 0x67, 0x50), 0, gk1SignatureInterrogationBug, gk1PatchInterrogationBug },
{ 212, "day 5 phone freeze", 1, PATCH_MAGICDWORD(0x35, 0x03, 0x65, 0x1a), 0, gk1SignatureDay5PhoneFreeze, gk1PatchDay5PhoneFreeze },
{ 230, "day 6 police beignet timer issue", 1, PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -16, gk1SignatureDay6PoliceBeignet, gk1PatchDay6PoliceBeignet },
{ 230, "day 6 police sleep timer issue", 1, PATCH_MAGICDWORD(0x34, 0xdc, 0x00, 0x65), -5, gk1SignatureDay6PoliceSleep, gk1PatchDay6PoliceSleep },
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 554a6b6a2c..ef61b2e28a 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -727,7 +727,7 @@ void logKernelCall(const KernelFunction *kernelCall, const KernelSubFunction *ke
switch (mobj->getType()) {
case SEG_TYPE_HUNK:
{
- HunkTable *ht = (HunkTable*)mobj;
+ HunkTable *ht = (HunkTable *)mobj;
int index = argv[parmNr].offset;
if (ht->isValidEntry(index)) {
// NOTE: This ", deleted" isn't as useful as it could
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index 04c61f7b7c..cc127c8dbc 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -691,7 +691,7 @@ void SegManager::memcpy(reg_t dest, const byte* src, size_t n) {
if (dest_r.isRaw) {
// raw -> raw
- ::memcpy((char*)dest_r.raw, src, n);
+ ::memcpy((char *)dest_r.raw, src, n);
} else {
// raw -> non-raw
for (uint i = 0; i < n; i++)
diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp
index 73d81baf3a..36b7d92c07 100644
--- a/engines/sci/engine/segment.cpp
+++ b/engines/sci/engine/segment.cpp
@@ -294,18 +294,19 @@ void SciString::fromString(const Common::String &string) {
if (_type != 3)
error("SciString::fromString(): Array is not a string");
- if (string.size() > _size)
- setSize(string.size());
+ setSize(string.size() + 1);
for (uint32 i = 0; i < string.size(); i++)
_data[i] = string[i];
+
+ _data[string.size()] = 0;
}
SegmentRef StringTable::dereference(reg_t pointer) {
SegmentRef ret;
ret.isRaw = true;
ret.maxSize = _table[pointer.offset].getSize();
- ret.raw = (byte*)_table[pointer.offset].getRawData();
+ ret.raw = (byte *)_table[pointer.offset].getRawData();
return ret;
}
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index 009a2558ce..54cf7b98af 100644
--- a/engines/sci/engine/segment.h
+++ b/engines/sci/engine/segment.h
@@ -370,7 +370,7 @@ public:
#ifdef ENABLE_SCI32
-template <typename T>
+template<typename T>
class SciArray {
public:
SciArray() : _type(-1), _data(NULL), _size(0), _actualSize(0) { }
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index cbe4736ba2..162dce9fcc 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -235,6 +235,9 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
if (g_sci->getGameId() == GID_TORIN && script == 64036) {
// Script 64036 in Torin's Passage is empty and contains an invalid
// (empty) export
+ } else if (g_sci->getGameId() == GID_RAMA && script == 64908) {
+ // Script 64908 in the demo of RAMA contains an invalid (empty)
+ // export
} else
#endif
error("Request for invalid exported function 0x%x of script %d", pubfunct, script);
diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp
index f68b74e1e0..a556134e32 100644
--- a/engines/sci/engine/workarounds.cpp
+++ b/engines/sci/engine/workarounds.cpp
@@ -353,7 +353,7 @@ const SciWorkaroundEntry kNewWindow_workarounds[] = {
// gameID, room,script,lvl, object-name, method-name, call,index, workaround
const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[] = {
- { GID_QFG4, 100, 100, 0, "doMovie", "<noname144>", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #3034506
+ { GID_QFG4, 100, 100, 0, "doMovie", "changeState", -1, 0, { WORKAROUND_IGNORE, 0 } }, // after the Sierra logo, no flags are passed, thus the call is meaningless - bug #3034506
SCI_WORKAROUNDENTRY_TERMINATOR
};
diff --git a/engines/sci/graphics/controls16.cpp b/engines/sci/graphics/controls16.cpp
index ab54e468d1..7c09969717 100644
--- a/engines/sci/graphics/controls16.cpp
+++ b/engines/sci/graphics/controls16.cpp
@@ -297,7 +297,7 @@ void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *t
_paint16->eraseRect(rect);
_paint16->frameRect(rect);
rect.grow(-2);
- _ports->textGreyedOutput(style & 1 ? false : true);
+ _ports->textGreyedOutput(!(style & SCI_CONTROLS_STYLE_ENABLED));
_text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId);
_ports->textGreyedOutput(false);
rect.grow(1);
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp
index 50da48aaf3..52a5961070 100644
--- a/engines/sci/graphics/cursor.cpp
+++ b/engines/sci/graphics/cursor.cpp
@@ -59,10 +59,16 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc
_zoomColor = 0;
_zoomMultiplier = 0;
_cursorSurface = 0;
+
if (g_sci && g_sci->getGameId() == GID_KQ6 && g_sci->getPlatform() == Common::kPlatformWindows)
_useOriginalKQ6WinCursors = ConfMan.getBool("windows_cursors");
else
_useOriginalKQ6WinCursors = false;
+
+ if (g_sci && g_sci->getGameId() == GID_SQ4 && getSciVersion() == SCI_VERSION_1_1)
+ _useSilverSQ4CDCursors = ConfMan.getBool("silver_cursors");
+ else
+ _useSilverSQ4CDCursors = false;
}
GfxCursor::~GfxCursor() {
@@ -125,18 +131,28 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) {
error("cursor resource %d has invalid size", resourceId);
resourceData = resource->data;
- // hotspot is specified for SCI1 cursors
- hotspot.x = READ_LE_UINT16(resourceData);
- hotspot.y = READ_LE_UINT16(resourceData + 2);
- // bit 0 of resourceData[3] is set on <SCI1 games, which means center hotspot
- if ((hotspot.x == 0) && (hotspot.y == 256))
- hotspot.x = hotspot.y = SCI_CURSOR_SCI0_HEIGHTWIDTH / 2;
+
+ if (getSciVersion() <= SCI_VERSION_0_LATE) {
+ // SCI0 cursors contain hotspot flags, not actual hotspot coordinates.
+ // If bit 0 of resourceData[3] is set, the hotspot should be centered,
+ // otherwise it's in the top left of the mouse cursor.
+ hotspot.x = hotspot.y = resourceData[3] ? SCI_CURSOR_SCI0_HEIGHTWIDTH / 2 : 0;
+ } else {
+ // Cursors in newer SCI versions contain actual hotspot coordinates.
+ hotspot.x = READ_LE_UINT16(resourceData);
+ hotspot.y = READ_LE_UINT16(resourceData + 2);
+ }
// Now find out what colors we are supposed to use
colorMapping[0] = 0; // Black is hardcoded
colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded
colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR;
colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey
+ // Special case for the magnifier cursor in LB1 (bug #3487092).
+ // No other SCI0 game has a cursor resource of 1, so this is handled
+ // specifically for LB1.
+ if (g_sci->getGameId() == GID_LAURABOW && resourceId == 1)
+ colorMapping[3] = _screen->getColorWhite();
// Seek to actual data
resourceData += 4;
@@ -165,6 +181,11 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) {
rawBitmap = upscaledBitmap;
}
+ if (hotspot.x >= heightWidth || hotspot.y >= heightWidth) {
+ error("cursor %d's hotspot (%d, %d) is out of range of the cursor's dimensions (%dx%d)",
+ resourceId, hotspot.x, hotspot.y, heightWidth, heightWidth);
+ }
+
CursorMan.replaceCursor(rawBitmap, heightWidth, heightWidth, hotspot.x, hotspot.y, SCI_CURSOR_SCI0_TRANSPARENCYCOLOR);
kernelShow();
@@ -191,6 +212,26 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co
return;
}
+ // Use the alternate silver cursors in SQ4 CD, if requested
+ if (_useSilverSQ4CDCursors) {
+ switch(viewNum) {
+ case 850:
+ case 852:
+ case 854:
+ case 856:
+ celNum = 3;
+ break;
+ case 851:
+ case 853:
+ case 855:
+ case 999:
+ celNum = 2;
+ break;
+ default:
+ break;
+ }
+ }
+
if (!_cachedCursors.contains(viewNum))
_cachedCursors[viewNum] = new GfxView(_resMan, _screen, _palette, viewNum);
diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h
index 25109b3920..ac928f50bb 100644
--- a/engines/sci/graphics/cursor.h
+++ b/engines/sci/graphics/cursor.h
@@ -113,13 +113,18 @@ private:
bool _isVisible;
- // KQ6 Windows has different black and white cursors. If this is
- // true (set from the sci_originalkq6wincursors ini setting), then
- // we use these, and don't scale them by 2x like the rest of the
- // graphics, like SSCI did. These look very ugly, which is why
- // they aren't enabled by default.
+ // KQ6 Windows has different black and white cursors. If this is true (set
+ // from the windows_cursors ini setting), then we use these and don't scale
+ // them by 2x like the rest of the graphics, like SSCI did. These look very
+ // ugly, which is why they aren't enabled by default.
bool _useOriginalKQ6WinCursors;
+ // The CD version of SQ4 contains a complete set of silver mouse cursors.
+ // If this is true (set from the silver_cursors ini setting), then we use
+ // these instead and replace the game's gold cursors with their silver
+ // equivalents.
+ bool _useSilverSQ4CDCursors;
+
// Mac versions of games use a remap list to remap their cursors
Common::Array<uint16> _macCursorRemap;
};
diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp
index 7bb4162020..b12413ab69 100644
--- a/engines/sci/graphics/frameout.cpp
+++ b/engines/sci/graphics/frameout.cpp
@@ -61,12 +61,13 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd
}
GfxFrameout::~GfxFrameout() {
+ clear();
}
void GfxFrameout::clear() {
- _screenItems.clear();
+ deletePlaneItems(NULL_REG);
_planes.clear();
- _planePictures.clear();
+ deletePlanePictures(NULL_REG);
}
void GfxFrameout::kernelAddPlane(reg_t object) {
@@ -101,7 +102,7 @@ void GfxFrameout::kernelAddPlane(reg_t object) {
}
void GfxFrameout::kernelUpdatePlane(reg_t object) {
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
+ for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) {
if (it->object == object) {
// Read some information
it->priority = readSelectorValue(_segMan, object, SELECTOR(priority));
@@ -178,8 +179,10 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) {
}
void GfxFrameout::kernelDeletePlane(reg_t object) {
+ deletePlaneItems(object);
deletePlanePictures(object);
- for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
+
+ for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); ++it) {
if (it->object == object) {
_planes.erase(it);
Common::Rect planeRect;
@@ -193,10 +196,6 @@ void GfxFrameout::kernelDeletePlane(reg_t object) {
planeRect.left = (planeRect.left * screenRect.width()) / _scriptsRunningWidth;
planeRect.bottom = (planeRect.bottom * screenRect.height()) / _scriptsRunningHeight;
planeRect.right = (planeRect.right * screenRect.width()) / _scriptsRunningWidth;
- planeRect.clip(screenRect); // we need to do this, at least in gk1 on cemetary we get bottom right -> 201, 321
- // FIXME: The code above incorrectly added 1 pixel to the plane's
- // bottom and right, so probably the plane clipping code is no
- // longer necessary
// Blackout removed plane rect
_paint32->fillRect(planeRect, 0);
return;
@@ -216,12 +215,15 @@ void GfxFrameout::addPlanePicture(reg_t object, GuiResourceId pictureId, uint16
}
void GfxFrameout::deletePlanePictures(reg_t object) {
- for (PlanePictureList::iterator it = _planePictures.begin(); it != _planePictures.end(); it++) {
- if (it->object == object) {
+ PlanePictureList::iterator it = _planePictures.begin();
+
+ while (it != _planePictures.end()) {
+ if (it->object == object || object.isNull()) {
+ delete it->pictureCels;
delete it->picture;
- _planePictures.erase(it);
- deletePlanePictures(object);
- return;
+ it = _planePictures.erase(it);
+ } else {
+ ++it;
}
}
}
@@ -274,6 +276,29 @@ void GfxFrameout::kernelDeleteScreenItem(reg_t object) {
}
_screenItems.remove(itemEntry);
+ delete itemEntry;
+}
+
+void GfxFrameout::deletePlaneItems(reg_t planeObject) {
+ FrameoutList::iterator listIterator = _screenItems.begin();
+
+ while (listIterator != _screenItems.end()) {
+ bool objectMatches = false;
+ if (!planeObject.isNull()) {
+ reg_t itemPlane = readSelector(_segMan, (*listIterator)->object, SELECTOR(plane));
+ objectMatches = (planeObject == itemPlane);
+ } else {
+ objectMatches = true;
+ }
+
+ if (objectMatches) {
+ FrameoutEntry *itemEntry = *listIterator;
+ listIterator = _screenItems.erase(listIterator);
+ delete itemEntry;
+ } else {
+ ++listIterator;
+ }
+ }
}
FrameoutEntry *GfxFrameout::findScreenItem(reg_t object) {
@@ -498,7 +523,8 @@ void GfxFrameout::kernelFrameout() {
// There is a race condition lurking in SQ6, which causes the game to hang in the intro, when teleporting to Polysorbate LX.
// Since I first wrote the patch, the race has stopped occurring for me though.
// I'll leave this for investigation later, when someone can reproduce.
- if (it->pictureId == 0xffff)
+ //if (it->pictureId == 0xffff) // FIXME: This is what SSCI does, and fixes the intro of LSL7, but breaks the dialogs in GK1 (adds black boxes)
+ if (it->planeBack)
_paint32->fillRect(it->planeRect, it->planeBack);
GuiResourceId planeMainPictureId = it->pictureId;
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index a4a0a853e4..8c3cc261d5 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -94,6 +94,7 @@ public:
void kernelAddScreenItem(reg_t object);
void kernelUpdateScreenItem(reg_t object);
void kernelDeleteScreenItem(reg_t object);
+ void deletePlaneItems(reg_t planeObject);
FrameoutEntry *findScreenItem(reg_t object);
int16 kernelGetHighPlanePri();
void kernelAddPicAt(reg_t planeObj, GuiResourceId pictureId, int16 pictureX, int16 pictureY);
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index bff145ad53..7ecba5a24d 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -31,8 +31,8 @@
#include "common/memstream.h"
#include "common/system.h"
-#include "graphics/pict.h"
#include "graphics/surface.h"
+#include "graphics/decoders/pict.h"
namespace Sci {
@@ -201,18 +201,20 @@ void GfxMacIconBar::setInventoryIcon(int16 icon) {
}
Graphics::Surface *GfxMacIconBar::loadPict(ResourceId id) {
- Graphics::PictDecoder pictDecoder(Graphics::PixelFormat::createFormatCLUT8());
+ Graphics::PICTDecoder pictDecoder;
Resource *res = g_sci->getResMan()->findResource(id, false);
if (!res || res->size == 0)
return 0;
- byte palette[256 * 3];
- Common::SeekableReadStream *stream = new Common::MemoryReadStream(res->data, res->size);
- Graphics::Surface *surface = pictDecoder.decodeImage(stream, palette);
- remapColors(surface, palette);
+ Common::MemoryReadStream stream(res->data, res->size);
+ if (!pictDecoder.loadStream(stream))
+ return 0;
+
+ Graphics::Surface *surface = new Graphics::Surface();
+ surface->copyFrom(*pictDecoder.getSurface());
+ remapColors(surface, pictDecoder.getPalette());
- delete stream;
return surface;
}
@@ -221,7 +223,7 @@ Graphics::Surface *GfxMacIconBar::createImage(uint32 iconIndex, bool isSelected)
return loadPict(ResourceId(type, iconIndex + 1));
}
-void GfxMacIconBar::remapColors(Graphics::Surface *surf, byte *palette) {
+void GfxMacIconBar::remapColors(Graphics::Surface *surf, const byte *palette) {
byte *pixels = (byte *)surf->pixels;
// Remap to the screen palette
diff --git a/engines/sci/graphics/maciconbar.h b/engines/sci/graphics/maciconbar.h
index 43de37a904..eca10b804c 100644
--- a/engines/sci/graphics/maciconbar.h
+++ b/engines/sci/graphics/maciconbar.h
@@ -61,7 +61,7 @@ private:
Graphics::Surface *loadPict(ResourceId id);
Graphics::Surface *createImage(uint32 iconIndex, bool isSelected);
- void remapColors(Graphics::Surface *surf, byte *palette);
+ void remapColors(Graphics::Surface *surf, const byte *palette);
void drawIcon(uint16 index, bool selected);
void drawSelectedImage(uint16 index);
diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp
index 673729784f..47f34cf99d 100644
--- a/engines/sci/graphics/menu.cpp
+++ b/engines/sci/graphics/menu.cpp
@@ -286,7 +286,7 @@ void GfxMenu::kernelSetAttribute(uint16 menuId, uint16 itemId, uint16 attributeI
switch (attributeId) {
case SCI_MENU_ATTRIBUTE_ENABLED:
- itemEntry->enabled = value.isNull() ? false : true;
+ itemEntry->enabled = !value.isNull();
break;
case SCI_MENU_ATTRIBUTE_SAID:
itemEntry->saidVmPtr = value;
@@ -606,7 +606,7 @@ void GfxMenu::drawMenu(uint16 oldMenuId, uint16 newMenuId) {
listItemEntry = *listItemIterator;
if (listItemEntry->menuId == newMenuId) {
if (!listItemEntry->separatorLine) {
- _ports->textGreyedOutput(listItemEntry->enabled ? false : true);
+ _ports->textGreyedOutput(!listItemEntry->enabled);
_ports->moveTo(_menuRect.left, topPos);
_text16->DrawString(listItemEntry->textSplit.c_str());
_ports->moveTo(_menuRect.right - listItemEntry->textRightAlignedWidth - 5, topPos);
diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp
index 23177dfc7b..c951f3349d 100644
--- a/engines/sci/graphics/paint16.cpp
+++ b/engines/sci/graphics/paint16.cpp
@@ -513,7 +513,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
argc--; argv++;
break;
case SCI_DISPLAY_SETGREYEDOUTPUT:
- _ports->textGreyedOutput(argv[0].isNull() ? false : true);
+ _ports->textGreyedOutput(!argv[0].isNull());
argc--; argv++;
break;
case SCI_DISPLAY_SETFONT:
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 6469bc0cb3..4020518b72 100644
--- a/engines/sci/graphics/screen.cpp
+++ b/engines/sci/graphics/screen.cpp
@@ -438,7 +438,7 @@ void GfxScreen::bitsSaveScreen(Common::Rect rect, byte *screen, uint16 screenWid
screen += (rect.top * screenWidth) + rect.left;
for (y = rect.top; y < rect.bottom; y++) {
- memcpy(memoryPtr, (void*)screen, width); memoryPtr += width;
+ memcpy(memoryPtr, (void *)screen, width); memoryPtr += width;
screen += screenWidth;
}
}
@@ -458,7 +458,7 @@ void GfxScreen::bitsSaveDisplayScreen(Common::Rect rect, byte *&memoryPtr) {
}
for (y = rect.top; y < rect.bottom; y++) {
- memcpy(memoryPtr, (void*)screen, width); memoryPtr += width;
+ memcpy(memoryPtr, (void *)screen, width); memoryPtr += width;
screen += _displayWidth;
}
}
@@ -503,7 +503,7 @@ void GfxScreen::bitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *scr
screen += (rect.top * screenWidth) + rect.left;
for (y = rect.top; y < rect.bottom; y++) {
- memcpy((void*) screen, memoryPtr, width); memoryPtr += width;
+ memcpy((void *) screen, memoryPtr, width); memoryPtr += width;
screen += screenWidth;
}
}
@@ -523,7 +523,7 @@ void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) {
}
for (y = rect.top; y < rect.bottom; y++) {
- memcpy((void*) screen, memoryPtr, width); memoryPtr += width;
+ memcpy((void *) screen, memoryPtr, width); memoryPtr += width;
screen += _displayWidth;
}
}
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index 84547d9828..7eaa0168b8 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -100,7 +100,7 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1
// cX -> sets textColor to _textColors[X-1]
curCode = textCode[0];
curCodeParm = textCode[1];
- if (isdigit(static_cast<unsigned char>(curCodeParm))) {
+ if (Common::isDigit(curCodeParm)) {
curCodeParm -= '0';
} else {
curCodeParm = -1;
diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp
index fd6637f313..7894c7109c 100644
--- a/engines/sci/graphics/text32.cpp
+++ b/engines/sci/graphics/text32.cpp
@@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/sci/graphics/text16.cpp $
- * $Id: text16.cpp 55178 2011-01-08 23:16:44Z thebluegr $
- *
*/
#include "common/util.h"
@@ -176,13 +173,18 @@ void GfxText32::disposeTextBitmap(reg_t hunkId) {
_segMan->freeHunkEntry(hunkId);
}
-void GfxText32::drawTextBitmap(uint16 x, uint16 y, Common::Rect planeRect, reg_t textObject) {
+void GfxText32::drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject) {
reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap));
+ uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back));
// Sanity check: Check if the hunk is set. If not, either the game scripts
// didn't set it, or an old saved game has been loaded, where it wasn't set.
if (hunkId.isNull())
return;
+ // Negative coordinates indicate that text shouldn't be displayed
+ if (x < 0 || y < 0)
+ return;
+
byte *memoryPtr = _segMan->getHunkPointer(hunkId);
if (!memoryPtr)
@@ -207,7 +209,7 @@ void GfxText32::drawTextBitmap(uint16 x, uint16 y, Common::Rect planeRect, reg_t
for (int curY = 0; curY < height; curY++) {
for (int curX = 0; curX < width; curX++) {
byte pixel = surface[curByte++];
- if (pixel != skipColor)
+ if (pixel != skipColor && pixel != backColor)
_screen->putFontPixel(textY, curX + textX, curY, pixel);
}
}
@@ -295,6 +297,10 @@ int16 GfxText32::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
int16 maxTextWidth = 0, textWidth;
int16 totalHeight = 0, textHeight;
+ // Adjust maxWidth if we're using an upscaled font
+ if (_screen->fontIsUpscaled())
+ maxWidth = maxWidth * _screen->getDisplayWidth() / _screen->getWidth();
+
rect.top = rect.left = 0;
GfxFont *font = _cache->getFont(fontId);
@@ -321,6 +327,14 @@ int16 GfxText32::Size(Common::Rect &rect, const char *text, GuiResourceId fontId
rect.bottom = totalHeight;
rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth);
}
+
+ // Adjust the width/height if we're using an upscaled font
+ // for the scripts
+ if (_screen->fontIsUpscaled()) {
+ rect.right = rect.right * _screen->getWidth() / _screen->getDisplayWidth();
+ rect.bottom = rect.bottom * _screen->getHeight() / _screen->getDisplayHeight();
+ }
+
return rect.right;
}
diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h
index 3a411ce663..3505de85eb 100644
--- a/engines/sci/graphics/text32.h
+++ b/engines/sci/graphics/text32.h
@@ -18,9 +18,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/sci/graphics/text16.h $
- * $Id: text16.h 55178 2011-01-08 23:16:44Z thebluegr $
- *
*/
#ifndef SCI_GRAPHICS_TEXT32_H
@@ -37,7 +34,7 @@ public:
~GfxText32();
reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG);
void disposeTextBitmap(reg_t hunkId);
- void drawTextBitmap(uint16 x, uint16 y, Common::Rect planeRect, reg_t textObject);
+ void drawTextBitmap(int16 x, int16 y, Common::Rect planeRect, reg_t textObject);
int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font);
void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp
index d047eb10a1..b385c2c1db 100644
--- a/engines/sci/graphics/transitions.cpp
+++ b/engines/sci/graphics/transitions.cpp
@@ -52,8 +52,8 @@ static const GfxTransitionTranslateEntry oldTransitionIDs[] = {
{ 3, SCI_TRANSITIONS_STRAIGHT_FROM_LEFT, false },
{ 4, SCI_TRANSITIONS_STRAIGHT_FROM_BOTTOM, false },
{ 5, SCI_TRANSITIONS_STRAIGHT_FROM_TOP, false },
- { 6, SCI_TRANSITIONS_DIAGONALROLL_FROMCENTER, false },
- { 7, SCI_TRANSITIONS_DIAGONALROLL_TOCENTER, false },
+ { 6, SCI_TRANSITIONS_DIAGONALROLL_TOCENTER, false },
+ { 7, SCI_TRANSITIONS_DIAGONALROLL_FROMCENTER, false },
{ 8, SCI_TRANSITIONS_BLOCKS, false },
{ 9, SCI_TRANSITIONS_VERTICALROLL_TOCENTER, false },
{ 10, SCI_TRANSITIONS_HORIZONTALROLL_TOCENTER, false },
@@ -295,12 +295,12 @@ void GfxTransitions::fadeOut() {
int16 stepNr, colorNr;
// Sierra did not fade in/out color 255 for sci1.1, but they used it in
// several pictures (e.g. qfg3 demo/intro), so the fading looked weird
- int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 256 : 255;
+ int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254;
g_system->getPaletteManager()->grabPalette(oldPalette, 0, 256);
for (stepNr = 100; stepNr >= 0; stepNr -= 10) {
- for (colorNr = 1; colorNr < tillColorNr; colorNr++) {
+ for (colorNr = 1; colorNr <= tillColorNr; colorNr++) {
if (_palette->colorIsFromMacClut(colorNr)) {
workPalette[colorNr * 3 + 0] = oldPalette[colorNr * 3];
workPalette[colorNr * 3 + 1] = oldPalette[colorNr * 3 + 1];
@@ -311,7 +311,7 @@ void GfxTransitions::fadeOut() {
workPalette[colorNr * 3 + 2] = oldPalette[colorNr * 3 + 2] * stepNr / 100;
}
}
- g_system->getPaletteManager()->setPalette(workPalette + 3, 1, 254);
+ g_system->getPaletteManager()->setPalette(workPalette + 3, 1, tillColorNr);
g_sci->getEngineState()->wait(2);
}
}
@@ -322,10 +322,10 @@ void GfxTransitions::fadeIn() {
int16 stepNr;
// Sierra did not fade in/out color 255 for sci1.1, but they used it in
// several pictures (e.g. qfg3 demo/intro), so the fading looked weird
- int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 256 : 255;
+ int16 tillColorNr = getSciVersion() >= SCI_VERSION_1_1 ? 255 : 254;
for (stepNr = 0; stepNr <= 100; stepNr += 10) {
- _palette->kernelSetIntensity(1, tillColorNr, stepNr, true);
+ _palette->kernelSetIntensity(1, tillColorNr + 1, stepNr, true);
g_sci->getEngineState()->wait(2);
}
}
diff --git a/engines/sci/parser/said.cpp b/engines/sci/parser/said.cpp
index d44109faec..eff4a29f49 100644
--- a/engines/sci/parser/said.cpp
+++ b/engines/sci/parser/said.cpp
@@ -743,7 +743,7 @@ static void node_print_desc(ParseTreeNode* node) {
}
}
#else
-static void node_print_desc(ParseTreeNode*) { }
+static void node_print_desc(ParseTreeNode *) { }
#endif
diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index a5c4686b3b..e56158ecc1 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -534,7 +534,7 @@ bool Vocabulary::tokenizeString(ResultWordListList &retval, const char *sentence
do {
c = sentence[pos_in_sentence++];
- if (isalnum(c) || (c == '-' && wordLen) || (c >= 0x80)) {
+ if (Common::isAlnum(c) || (c == '-' && wordLen) || (c >= 0x80)) {
currentWord[wordLen] = lowerCaseMap[c];
++wordLen;
}
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 9171e5e5d9..77a6a40a92 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -609,7 +609,7 @@ int ResourceManager::addAppropriateSources() {
if (Common::File::exists("alt.map") && Common::File::exists("resource.alt"))
addSource(new VolumeResourceSource("resource.alt", addExternalMap("alt.map", 10), 10));
#endif
- } else if (Common::File::exists("Data1")) {
+ } else if (Common::MacResManager::exists("Data1")) {
// Mac SCI1.1+ file naming scheme
SearchMan.listMatchingMembers(files, "Data?*");
@@ -753,12 +753,10 @@ void ResourceManager::addScriptChunkSources() {
// to try to get to any scripts in there. The Lighthouse SCI2.1 demo
// does exactly this.
- Common::List<ResourceId> *resources = listResources(kResourceTypeScript);
+ Common::List<ResourceId> resources = listResources(kResourceTypeScript);
- if (resources->empty() && testResource(ResourceId(kResourceTypeChunk, 0)))
+ if (resources.empty() && testResource(ResourceId(kResourceTypeChunk, 0)))
addResourcesFromChunk(0);
-
- delete resources;
}
#endif
}
@@ -1045,13 +1043,13 @@ void ResourceManager::freeOldResources() {
}
}
-Common::List<ResourceId> *ResourceManager::listResources(ResourceType type, int mapNumber) {
- Common::List<ResourceId> *resources = new Common::List<ResourceId>;
+Common::List<ResourceId> ResourceManager::listResources(ResourceType type, int mapNumber) {
+ Common::List<ResourceId> resources;
ResourceMap::iterator itr = _resMap.begin();
while (itr != _resMap.end()) {
if ((itr->_value->getType() == type) && ((mapNumber == -1) || (itr->_value->getNumber() == mapNumber)))
- resources->push_back(itr->_value->_id);
+ resources.push_back(itr->_value->_id);
++itr;
}
@@ -1560,7 +1558,7 @@ void ResourceManager::readResourcePatches() {
name = (*x)->getName();
// SCI1 scheme
- if (isdigit(static_cast<unsigned char>(name[0]))) {
+ if (Common::isDigit(name[0])) {
char *end = 0;
resourceNr = strtol(name.c_str(), &end, 10);
bAdd = (*end == '.'); // Ensure the next character is the period
@@ -1568,7 +1566,7 @@ void ResourceManager::readResourcePatches() {
// SCI0 scheme
int resname_len = strlen(szResType);
if (scumm_strnicmp(name.c_str(), szResType, resname_len) == 0
- && !isalpha(static_cast<unsigned char>(name[resname_len + 1]))) {
+ && !Common::isAlpha(name[resname_len + 1])) {
resourceNr = atoi(name.c_str() + resname_len + 1);
bAdd = true;
}
@@ -2199,14 +2197,16 @@ void ResourceManager::detectSciVersion() {
// Handle SCI32 versions here
if (_volVersion >= kResVersionSci2) {
- Common::List<ResourceId> *heaps = listResources(kResourceTypeHeap);
+ Common::List<ResourceId> heaps = listResources(kResourceTypeHeap);
+ bool hasHeapResources = !heaps.empty();
+
// SCI2.1/3 and SCI1 Late resource maps are the same, except that
// SCI1 Late resource maps have the resource types or'd with
// 0x80. We differentiate between SCI2 and SCI2.1/3 based on that.
if (_mapVersion == kResVersionSci1Late) {
s_sciVersion = SCI_VERSION_2;
return;
- } else if (!heaps->empty()) {
+ } else if (hasHeapResources) {
s_sciVersion = SCI_VERSION_2_1;
return;
} else {
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 47602de017..294a4672e2 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -322,7 +322,7 @@ public:
* @param mapNumber For audio36 and sync36, limit search to this map
* @return The resource list
*/
- Common::List<ResourceId> *listResources(ResourceType type, int mapNumber = -1);
+ Common::List<ResourceId> listResources(ResourceType type, int mapNumber = -1);
void setAudioLanguage(int language);
int getAudioLanguage() const;
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index a3cf1b0c84..684e1a1d0d 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -185,6 +185,7 @@ void ResourceManager::processWavePatch(ResourceId resourceId, Common::String nam
file.open(name);
updateResource(resourceId, resSrc, file.size());
+ _sources.push_back(resSrc);
debugC(1, kDebugLevelResMan, "Patching %s - OK", name.c_str());
}
@@ -197,7 +198,7 @@ void ResourceManager::readWaveAudioPatches() {
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
Common::String name = (*x)->getName();
- if (isdigit(static_cast<unsigned char>(name[0])))
+ if (Common::isDigit(name[0]))
processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name);
}
}
@@ -538,11 +539,10 @@ bool ResourceManager::isGMTrackIncluded() {
// Read the first song and check if it has a GM track
bool result = false;
- Common::List<ResourceId> *resources = listResources(kResourceTypeSound, -1);
- Common::sort(resources->begin(), resources->end());
- Common::List<ResourceId>::iterator itr = resources->begin();
+ Common::List<ResourceId> resources = listResources(kResourceTypeSound, -1);
+ Common::sort(resources.begin(), resources.end());
+ Common::List<ResourceId>::iterator itr = resources.begin();
int firstSongId = itr->getNumber();
- delete resources;
SoundResource *song1 = new SoundResource(firstSongId, this, soundVersion);
if (!song1) {
@@ -892,10 +892,10 @@ void AudioVolumeResourceSource::loadResource(ResourceManager *resMan, Resource *
}
bool ResourceManager::addAudioSources() {
- Common::List<ResourceId> *resources = listResources(kResourceTypeMap);
- Common::List<ResourceId>::iterator itr = resources->begin();
+ Common::List<ResourceId> resources = listResources(kResourceTypeMap);
+ Common::List<ResourceId>::iterator itr;
- while (itr != resources->end()) {
+ for (itr = resources.begin(); itr != resources.end(); ++itr) {
ResourceSource *src = addSource(new IntMapResourceSource("MAP", itr->getNumber()));
if ((itr->getNumber() == 65535) && Common::File::exists("RESOURCE.SFX"))
@@ -904,12 +904,8 @@ bool ResourceManager::addAudioSources() {
addSource(new AudioVolumeResourceSource(this, "RESOURCE.AUD", src, 0));
else
return false;
-
- ++itr;
}
- delete resources;
-
return true;
}
@@ -943,8 +939,9 @@ void ResourceManager::changeAudioDirectory(Common::String path) {
audioResourceName = Common::String::format("%s/RESOURCE.AUD", path.c_str());
}
- Common::List<ResourceId> *resources = listResources(kResourceTypeMap);
- for (Common::List<ResourceId>::iterator it = resources->begin(); it != resources->end(); ++it) {
+ Common::List<ResourceId> resources = listResources(kResourceTypeMap);
+ Common::List<ResourceId>::iterator it;
+ for (it = resources.begin(); it != resources.end(); ++it) {
// Don't readd 65535.map or resource.sfx
if ((it->getNumber() == 65535))
continue;
@@ -953,8 +950,6 @@ void ResourceManager::changeAudioDirectory(Common::String path) {
addSource(new AudioVolumeResourceSource(this, audioResourceName, src, 0));
}
- delete resources;
-
// Rescan the newly added resources
scanNewSources();
}
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 00731fc1cf..4ae55cbcba 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -194,6 +194,7 @@ Common::Error SciEngine::run() {
ConfMan.registerDefault("sci_originalsaveload", "false");
ConfMan.registerDefault("native_fb01", "false");
ConfMan.registerDefault("windows_cursors", "false"); // Windows cursors for KQ6 Windows
+ ConfMan.registerDefault("silver_cursors", "false"); // Silver cursors for SQ4 CD
_resMan = new ResourceManager();
assert(_resMan);
diff --git a/engines/sci/sound/drivers/amigamac.cpp b/engines/sci/sound/drivers/amigamac.cpp
index 41697d4a07..131a85f371 100644
--- a/engines/sci/sound/drivers/amigamac.cpp
+++ b/engines/sci/sound/drivers/amigamac.cpp
@@ -524,7 +524,7 @@ MidiDriver_AmigaMac::InstrumentSample *MidiDriver_AmigaMac::readInstrumentSCI0(C
instrument->size = seg_size[0];
instrument->loop_size = seg_size[1];
- instrument->loop = (int8*)malloc(instrument->loop_size + 1);
+ instrument->loop = (int8 *)malloc(instrument->loop_size + 1);
memcpy(instrument->loop, instrument->samples + loop_offset, instrument->loop_size);
instrument->samples[instrument->size] = instrument->loop[0];
@@ -708,7 +708,7 @@ void MidiDriver_AmigaMac::generateSamples(int16 *data, int len) {
if (len == 0)
return;
- int16 *buffers = (int16*)malloc(len * 2 * kChannels);
+ int16 *buffers = (int16 *)malloc(len * 2 * kChannels);
memset(buffers, 0, len * 2 * kChannels);
@@ -869,7 +869,7 @@ bool MidiDriver_AmigaMac::loadInstrumentsSCI0Mac(Common::SeekableReadStream &fil
instrument->size = seg_size[0];
instrument->loop_size = seg_size[1] - seg_size[0];
- instrument->loop = (int8*)malloc(instrument->loop_size + 1);
+ instrument->loop = (int8 *)malloc(instrument->loop_size + 1);
memcpy(instrument->loop, instrument->samples + loop_offset, instrument->loop_size);
instrument->samples[instrument->size] = instrument->loop[0];
diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp
index 4ffa8d7590..09cab75c39 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -37,8 +37,8 @@
namespace Sci {
-SciMusic::SciMusic(SciVersion soundVersion)
- : _soundVersion(soundVersion), _soundOn(true), _masterVolume(0), _globalReverb(0) {
+SciMusic::SciMusic(SciVersion soundVersion, bool useDigitalSFX)
+ : _soundVersion(soundVersion), _soundOn(true), _masterVolume(0), _globalReverb(0), _useDigitalSFX(useDigitalSFX) {
// Reserve some space in the playlist, to avoid expensive insertion
// operations
@@ -122,8 +122,6 @@ void SciMusic::init() {
error("Failed to initialize sound driver");
}
- _bMultiMidi = ConfMan.getBool("multi_midi");
-
// Find out what the first possible channel is (used, when doing channel
// remapping).
_driverFirstChannel = _pMidiDrv->getFirstChannel();
@@ -285,10 +283,10 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
SoundResource::Track *track = pSnd->soundRes->getTrackByType(_pMidiDrv->getPlayId());
// If MIDI device is selected but there is no digital track in sound
- // resource try to use adlib's digital sample if possible. Also, if the
+ // resource try to use Adlib's digital sample if possible. Also, if the
// track couldn't be found, load the digital track, as some games depend on
// this (e.g. the Longbow demo).
- if (!track || (_bMultiMidi && track->digitalChannelNr == -1)) {
+ if (!track || (_useDigitalSFX && track->digitalChannelNr == -1)) {
SoundResource::Track *digital = pSnd->soundRes->getDigitalTrack();
if (digital)
track = digital;
diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h
index fa6f538a7e..1f798c90d7 100644
--- a/engines/sci/sound/music.h
+++ b/engines/sci/sound/music.h
@@ -120,7 +120,7 @@ typedef Common::Array<uint32> MidiCommandQueue;
class SciMusic : public Common::Serializable {
public:
- SciMusic(SciVersion soundVersion);
+ SciMusic(SciVersion soundVersion, bool useDigitalSFX);
~SciMusic();
void init();
@@ -210,9 +210,8 @@ protected:
MidiPlayer *_pMidiDrv;
uint32 _dwTempo;
- // Mixed AdLib/MIDI mode: when enabled from the ScummVM sound options screen,
- // and a sound has a digital track, the sound from the AdLib track is played
- bool _bMultiMidi;
+ // If true and a sound has a digital track, the sound from the AdLib track is played
+ bool _useDigitalSFX;
private:
MusicList _playList;
diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp
index 274c532779..b8be898abc 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -32,20 +32,30 @@
namespace Sci {
+//#define ENABLE_SFX_TYPE_SELECTION
+
SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) :
_resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) {
- _music = new SciMusic(_soundVersion);
- _music->init();
+#ifdef ENABLE_SFX_TYPE_SELECTION
// Check if the user wants synthesized or digital sound effects in SCI1.1
- // or later games
- _bMultiMidi = ConfMan.getBool("multi_midi");
+ // games based on the multi_midi config setting
+
// In SCI2 and later games, this check should always be true - there was
// always only one version of each sound effect or digital music track
// (e.g. the menu music in GK1 - there is a sound effect with the same
// resource number, but it's totally unrelated to the menu music).
- if (getSciVersion() >= SCI_VERSION_2)
- _bMultiMidi = true;
+ // The GK1 demo (very late SCI1.1) does the same thing
+ // TODO: Check the QFG4 demo
+
+ _useDigitalSFX = (getSciVersion() >= SCI_VERSION_2 || g_sci->getGameId() == GID_GK1 || ConfMan.getBool("multi_midi"));
+#else
+ // Always prefer digital sound effects
+ _useDigitalSFX = true;
+#endif
+
+ _music = new SciMusic(_soundVersion, _useDigitalSFX);
+ _music->init();
}
SoundCommandParser::~SoundCommandParser() {
@@ -84,16 +94,14 @@ void SoundCommandParser::initSoundResource(MusicEntry *newSound) {
// effects map)
bool checkAudioResource = getSciVersion() >= SCI_VERSION_1_1;
// Hoyle 4 has garbled audio resources in place of the sound resources.
- // The demo of GK1 has no alternate sound effects.
- if ((g_sci->getGameId() == GID_HOYLE4) ||
- (g_sci->getGameId() == GID_GK1 && g_sci->isDemo()))
+ if (g_sci->getGameId() == GID_HOYLE4)
checkAudioResource = false;
if (checkAudioResource && _resMan->testResource(ResourceId(kResourceTypeAudio, newSound->resourceId))) {
// Found a relevant audio resource, create an audio stream if there is
// no associated sound resource, or if both resources exist and the
// user wants the digital version.
- if (_bMultiMidi || !newSound->soundRes) {
+ if (_useDigitalSFX || !newSound->soundRes) {
int sampleLen;
newSound->pStreamAud = _audio->getAudioStream(newSound->resourceId, 65535, &sampleLen);
newSound->soundType = Audio::Mixer::kSpeechSoundType;
@@ -485,7 +493,7 @@ void SoundCommandParser::processUpdateCues(reg_t obj) {
} else {
// Slot actually has no data (which would mean that a sound-resource w/
// unsupported data is used.
- // (example lsl5 - sound resource 744 - it's roland exclusive
+ // (example lsl5 - sound resource 744 - it's Roland exclusive
writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
// If we don't set signal here, at least the switch to the mud wrestling
// room in lsl5 will not work.
diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h
index c1dce014d2..d76f969c7d 100644
--- a/engines/sci/sound/soundcmd.h
+++ b/engines/sci/sound/soundcmd.h
@@ -111,7 +111,9 @@ private:
SciMusic *_music;
AudioPlayer *_audio;
SciVersion _soundVersion;
- bool _bMultiMidi;
+ // If true and an alternative digital sound effect exists, the digital
+ // sound effect is preferred instead
+ bool _useDigitalSFX;
void processInitSound(reg_t obj);
void processDisposeSound(reg_t obj);