diff options
| author | Matthew Hoops | 2012-03-20 14:18:57 -0400 |
|---|---|---|
| committer | Matthew Hoops | 2012-03-20 14:49:16 -0400 |
| commit | 71756bdf4eae5ba9cc3f329b85e894f04640aaef (patch) | |
| tree | 40d464262da107ab5eed82f198685209161ebac1 /engines/sci | |
| parent | 03eba05b09e5c9e5a351f8111185934b92a3fed3 (diff) | |
| parent | 3c3576a224b92c703b4e8ea20008ac8a069980dd (diff) | |
| download | scummvm-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')
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); |
