aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/features.cpp9
-rw-r--r--engines/sci/engine/kernel_tables.h6
-rw-r--r--engines/sci/engine/kfile.cpp11
-rw-r--r--engines/sci/engine/kgraphics.cpp112
-rw-r--r--engines/sci/engine/klists.cpp18
-rw-r--r--engines/sci/engine/kmenu.cpp2
-rw-r--r--engines/sci/engine/kpathing.cpp1
-rw-r--r--engines/sci/engine/kscripts.cpp10
-rw-r--r--engines/sci/engine/kstring.cpp24
-rw-r--r--engines/sci/engine/message.cpp2
-rw-r--r--engines/sci/engine/savegame.cpp22
-rw-r--r--engines/sci/engine/script_patches.cpp62
-rw-r--r--engines/sci/engine/scriptdebug.cpp2
-rw-r--r--engines/sci/engine/seg_manager.cpp2
-rw-r--r--engines/sci/engine/segment.cpp7
-rw-r--r--engines/sci/engine/segment.h2
-rw-r--r--engines/sci/engine/vm.cpp3
-rw-r--r--engines/sci/engine/workarounds.cpp2
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
};