diff options
Diffstat (limited to 'engines/sci/engine')
-rw-r--r-- | engines/sci/engine/features.cpp | 9 | ||||
-rw-r--r-- | engines/sci/engine/kernel_tables.h | 6 | ||||
-rw-r--r-- | engines/sci/engine/kfile.cpp | 11 | ||||
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 112 | ||||
-rw-r--r-- | engines/sci/engine/klists.cpp | 18 | ||||
-rw-r--r-- | engines/sci/engine/kmenu.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/kpathing.cpp | 1 | ||||
-rw-r--r-- | engines/sci/engine/kscripts.cpp | 10 | ||||
-rw-r--r-- | engines/sci/engine/kstring.cpp | 24 | ||||
-rw-r--r-- | engines/sci/engine/message.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 22 | ||||
-rw-r--r-- | engines/sci/engine/script_patches.cpp | 62 | ||||
-rw-r--r-- | engines/sci/engine/scriptdebug.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.cpp | 2 | ||||
-rw-r--r-- | engines/sci/engine/segment.cpp | 7 | ||||
-rw-r--r-- | engines/sci/engine/segment.h | 2 | ||||
-rw-r--r-- | engines/sci/engine/vm.cpp | 3 | ||||
-rw-r--r-- | engines/sci/engine/workarounds.cpp | 2 |
18 files changed, 210 insertions, 87 deletions
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 }; |