aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/detection.cpp9
-rw-r--r--engines/sci/engine/game.cpp8
-rw-r--r--engines/sci/engine/kernel.cpp47
-rw-r--r--engines/sci/engine/kernel.h24
-rw-r--r--engines/sci/engine/kgraphics.cpp2
-rw-r--r--engines/sci/engine/savegame.cpp2
-rw-r--r--engines/sci/engine/scriptdebug.cpp2
-rw-r--r--engines/sci/engine/seg_manager.cpp2
-rw-r--r--engines/sci/engine/vm.cpp14
-rw-r--r--engines/sci/engine/vm.h2
-rw-r--r--engines/sci/sci.cpp10
-rw-r--r--engines/sci/sci.h11
12 files changed, 84 insertions, 49 deletions
diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp
index af03f1269c..a9dac98572 100644
--- a/engines/sci/detection.cpp
+++ b/engines/sci/detection.cpp
@@ -31,7 +31,6 @@
namespace Sci {
-#define GF_FOR_SCI0_BEFORE_395 (GF_SCI0_OLD | GF_SCI0_OLDGETTIME)
#define GF_FOR_SCI0_BEFORE_629 GF_SCI0_OLDGETTIME
// Titles of the games
@@ -219,7 +218,7 @@ static const struct SciGameDescription SciGameDescriptions[] = {
{"resource.map", 0, "39485580d34a72997f3d5b3aba4d24f1", 426},
{"resource.001", 0, "11391434f41c834090d7a1e9488ce936", 129739},
{NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH},
- GF_FOR_SCI0_BEFORE_395,
+ GF_FOR_SCI0_BEFORE_629,
SCI_VERSION_AUTODETECT,
SCI_VERSION_0
},
@@ -1032,7 +1031,7 @@ static const struct SciGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "851a62d00972dc4002f472cc0d84e71d", 333777},
{"resource.007", 0, "851a62d00972dc4002f472cc0d84e71d", 341038},
{NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH},
- GF_FOR_SCI0_BEFORE_395,
+ GF_FOR_SCI0_BEFORE_629,
SCI_VERSION_AUTODETECT,
SCI_VERSION_0
},
@@ -1049,7 +1048,7 @@ static const struct SciGameDescription SciGameDescriptions[] = {
{"resource.006", 0, "0c8566848a76eea19a6d6220914030a7", 337288},
{"resource.007", 0, "0c8566848a76eea19a6d6220914030a7", 343882},
{NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH},
- GF_FOR_SCI0_BEFORE_395,
+ GF_FOR_SCI0_BEFORE_629,
SCI_VERSION_AUTODETECT,
SCI_VERSION_0
},
@@ -1616,7 +1615,7 @@ static const struct SciGameDescription SciGameDescriptions[] = {
{"resource.005", 0, "96033f57accfca903750413fd09193c8", 274953},
{"resource.006", 0, "96033f57accfca903750413fd09193c8", 345818},
{NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH},
- GF_FOR_SCI0_BEFORE_395,
+ GF_FOR_SCI0_BEFORE_629,
SCI_VERSION_AUTODETECT,
SCI_VERSION_0
},
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp
index e35fbf99f8..ea03705fc2 100644
--- a/engines/sci/engine/game.cpp
+++ b/engines/sci/engine/game.cpp
@@ -257,7 +257,7 @@ static int create_class_table_sci0(EngineState *s) {
Resource *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, scriptnr), 0);
if (script) {
- if (s->_flags & GF_SCI0_OLD)
+ if (s->_kernel->hasOldScriptHeader())
magic_offset = seeker = 2;
else
magic_offset = seeker = 0;
@@ -327,6 +327,9 @@ int script_init_engine(EngineState *s) {
s->kernel_opt_flags = 0;
+ s->_kernel = new Kernel(s->resmgr);
+ s->_vocabulary = new Vocabulary(s->resmgr);
+
if (s->_version >= SCI_VERSION_1_1)
result = create_class_table_sci11(s);
else
@@ -367,9 +370,6 @@ int script_init_engine(EngineState *s) {
s->_executionStack.clear(); // Start without any execution stack
s->execution_stack_base = -1; // No vm is running yet
- s->_kernel = new Kernel(s->resmgr, (s->_flags & GF_SCI0_OLD));
- s->_vocabulary = new Vocabulary(s->resmgr);
-
s->restarting_flags = SCI_GAME_IS_NOT_RESTARTING;
s->bp_list = NULL; // No breakpoints defined
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index f869a3a9ea..ddcaf53df9 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -367,10 +367,11 @@ static const char *argtype_description[] = {
"Arithmetic"
};
-Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) {
+Kernel::Kernel(ResourceManager *resmgr) : _resmgr(resmgr) {
memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t
- loadSelectorNames(isOldSci0);
+ detectOldScriptHeader(); // must be called before loadSelectorNames()
+ loadSelectorNames();
mapSelectors(); // Map a few special selectors for later use
loadOpcodes();
loadKernelNames();
@@ -390,6 +391,11 @@ Kernel::~Kernel() {
}
void Kernel::printAutoDetectedFeatures() {
+ if (_oldScriptHeader)
+ printf("Kernel auto-detection: game found to have old headers for script blocks\n");
+ else
+ printf("Kernel auto-detection: game found to have newer headers for script blocks\n");
+
if (_oldGfxFunctions)
printf("Kernel auto-detection: game found to be using old graphics functions\n");
else
@@ -411,15 +417,44 @@ void Kernel::printAutoDetectedFeatures() {
printf("Kernel auto-detection: found SCI0 game using a SCI1 kernel table\n");
}
-void Kernel::loadSelectorNames(bool isOldSci0) {
- int count;
+void Kernel::detectOldScriptHeader() {
+ if (_resmgr->_sciVersion != SCI_VERSION_0) {
+ _oldScriptHeader = false;
+ return;
+ }
+
+ Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0);
+
+ if (!r) // No such resource?
+ error("Kernel: Could not retrieve selector names");
+
+ int count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off
+
+ _oldScriptHeader = true;
+
+ for (int i = 0; i < count; i++) {
+ int offset = READ_LE_UINT16(r->data + 2 + i * 2);
+ int len = READ_LE_UINT16(r->data + offset);
+
+ Common::String tmp((const char *)r->data + offset + 2, len);
+
+ // We determine if the game has old script headers by the existence of the
+ // "setTarget" selector. The "motionInited" selector can also be used for the
+ // same purpose
+ if (tmp == "setTarget") {
+ _oldScriptHeader = false;
+ break;
+ }
+ }
+}
+void Kernel::loadSelectorNames() {
Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0);
if (!r) // No such resource?
error("Kernel: Could not retrieve selector names");
- count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off
+ int count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off
for (int i = 0; i < count; i++) {
int offset = READ_LE_UINT16(r->data + 2 + i * 2);
@@ -431,7 +466,7 @@ void Kernel::loadSelectorNames(bool isOldSci0) {
// Early SCI versions used the LSB in the selector ID as a read/write
// toggle. To compensate for that, we add every selector name twice.
- if (isOldSci0)
+ if (_oldScriptHeader)
_selectorNames.push_back(tmp);
}
}
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 9c92519cf0..e73914a7e7 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -57,7 +57,7 @@ struct KernelFuncWithSignature {
class Kernel {
public:
- Kernel(ResourceManager *resmgr, bool isOldSci0);
+ Kernel(ResourceManager *resmgr);
~Kernel();
uint getOpcodesSize() const { return _opcodes.size(); }
@@ -84,6 +84,16 @@ public:
bool hasKernelFunction(const char *functionName) const;
/**
+ * Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2).
+ * Old SCI versions used two word header for script blocks (first word equal
+ * to 0x82, meaning of the second one unknown). New SCI versions used one
+ * word header.
+ * Also, old SCI versions assign 120 degrees to left & right, and 60 to up
+ * and down. Later versions use an even 90 degree distribution.
+ */
+ bool hasOldScriptHeader() const { return _oldScriptHeader; }
+
+ /**
* Applies to all versions before 0.000.502
* Old SCI versions used to interpret the third DrawPic() parameter inversely,
* with the opposite default value (obviously).
@@ -127,7 +137,12 @@ private:
/**
* Loads the kernel selector names.
*/
- void loadSelectorNames(bool isOldSci0);
+ void loadSelectorNames();
+
+ /**
+ * Maps special selectors
+ */
+ void mapSelectors();
/**
* Prints auto-detected features from selectors
@@ -135,9 +150,9 @@ private:
void printAutoDetectedFeatures();
/**
- * Maps special selectors
+ * Detects if the game is using older script headers
*/
- void mapSelectors();
+ void detectOldScriptHeader();
/**
* Maps kernel functions
@@ -151,6 +166,7 @@ private:
bool loadOpcodes();
ResourceManager *_resmgr;
+ bool _oldScriptHeader;
bool _oldGfxFunctions;
bool _hasLofsAbsolute;
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 435dd39d5a..d46ce3b938 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -696,7 +696,7 @@ void _k_dirloop(reg_t obj, uint16 angle, EngineState *s, int funct_nr, int argc,
angle %= 360;
- if (!(s->_flags & GF_SCI0_OLD)) {
+ if (!s->_kernel->hasOldScriptHeader()) {
if (angle < 45)
loop = 3;
else if (angle < 136)
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index bfff828745..f44af2b1cd 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -497,7 +497,7 @@ static SegmentId find_unique_seg_by_type(SegManager *self, int type) {
}
static byte *find_unique_script_block(EngineState *s, byte *buf, int type) {
- if (s->_flags & GF_SCI0_OLD)
+ if (s->_kernel->hasOldScriptHeader())
buf += 2;
do {
diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index a524ddd365..d5f0a21385 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -243,7 +243,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
int stackframe = (scr[pos.offset + 2] >> 1) + (*debugState.p_restadjust);
int argc = ((*debugState.p_sp)[- stackframe - 1]).offset;
- if (!(s->_flags & GF_SCI0_OLD))
+ if (!s->_kernel->hasOldScriptHeader())
argc += (*debugState.p_restadjust);
printf(" Kernel params: (");
diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp
index d81768c9c8..74486ef015 100644
--- a/engines/sci/engine/seg_manager.cpp
+++ b/engines/sci/engine/seg_manager.cpp
@@ -138,7 +138,7 @@ void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) {
if (!script || (s->_version >= SCI_VERSION_1_1 && !heap)) {
error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap");
}
- if (s->_flags & GF_SCI0_OLD) {
+ if (s->_kernel->hasOldScriptHeader()) {
scr.buf_size = script->size + READ_LE_UINT16(script->data) * 2;
//locals_size = READ_LE_UINT16(script->data) * 2;
} else if (s->_version < SCI_VERSION_1_1) {
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index b3852f10ef..c6643b8a90 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -961,7 +961,7 @@ void run_vm(EngineState *s, int restoring) {
gc_countdown(s);
xs->sp -= (opparams[1] >> 1) + 1;
- if (!(s->_flags & GF_SCI0_OLD)) {
+ if (!s->_kernel->hasOldScriptHeader()) {
xs->sp -= restadjust;
s->r_amp_rest = 0; // We just used up the restadjust, remember?
}
@@ -971,7 +971,7 @@ void run_vm(EngineState *s, int restoring) {
} else {
int argc = ASSERT_ARITHMETIC(xs->sp[0]);
- if (!(s->_flags & GF_SCI0_OLD))
+ if (!s->_kernel->hasOldScriptHeader())
argc += restadjust;
if (s->_kernel->_kernelFuncs[opparams[0]].signature
@@ -988,7 +988,7 @@ void run_vm(EngineState *s, int restoring) {
xs_new = &(s->_executionStack.back());
s->_executionStackPosChanged = true;
- if (!(s->_flags & GF_SCI0_OLD))
+ if (!s->_kernel->hasOldScriptHeader())
restadjust = s->r_amp_rest;
}
@@ -1500,7 +1500,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select
// Early SCI versions used the LSB in the selector ID as a read/write
// toggle, meaning that we must remove it for selector lookup.
- if (s->_flags & GF_SCI0_OLD)
+ if (s->_kernel->hasOldScriptHeader())
selector_id &= ~1;
if (!obj) {
@@ -1659,7 +1659,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
Script *scr = s->seg_manager->getScript(seg_id);
- if (s->_flags & GF_SCI0_OLD) {
+ if (s->_kernel->hasOldScriptHeader()) {
//
int locals_nr = READ_LE_UINT16(script->data);
@@ -1835,7 +1835,7 @@ int script_instantiate(EngineState *s, int script_nr) {
}
void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) {
- reg_t reg = make_reg(seg, (s->_flags & GF_SCI0_OLD) ? 2 : 0);
+ reg_t reg = make_reg(seg, s->_kernel->hasOldScriptHeader() ? 2 : 0);
int objtype, objlength;
Script *scr = s->seg_manager->getScript(seg);
@@ -1879,7 +1879,7 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) {
}
void script_uninstantiate(EngineState *s, int script_nr) {
- reg_t reg = make_reg(0, (s->_flags & GF_SCI0_OLD) ? 2 : 0);
+ reg_t reg = make_reg(0, s->_kernel->hasOldScriptHeader() ? 2 : 0);
reg.segment = s->seg_manager->segGet(script_nr);
Script *scr = script_locate_by_segment(s, reg.segment);
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index adaa064a6c..0536ec32ab 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -203,7 +203,7 @@ struct selector_map_t {
Selector printLang; /**< Used for i18n */
Selector subtitleLang;
Selector parseLang;
- Selector motionCue; // Used to detect newer graphics functions semantics.
+ Selector motionCue; // Used to detect newer graphics functions semantics
Selector sightAngle; // Used to detect some SCI0/SCI01 games which need a SCI1 table
Selector setVol; // Used to detect newer sound semantics
Selector egoMoveSpeed; // Used to detect SCI1 games which use absolute values in lofs
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 698983acaf..09c433edc2 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -151,19 +151,13 @@ Common::Error SciEngine::run() {
if (version < SCI_VERSION_1) {
// SCI0/SCI01
} else if (version == SCI_VERSION_1) {
- // SCI1
-
- if (flags & GF_SCI0_OLD ||
- flags & GF_SCI0_OLDGETTIME) {
+ if (flags & GF_SCI0_OLDGETTIME) {
error("This game entry is erroneous. It's marked as SCI1, but it has SCI0 flags set");
}
} else if (version == SCI_VERSION_1_1 || version == SCI_VERSION_32) {
- if (flags & GF_SCI0_OLD ||
- flags & GF_SCI0_OLDGETTIME) {
+ if (flags & GF_SCI0_OLDGETTIME) {
error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI0 flags set");
}
-
- // SCI1.1 / SCI32
} else {
error ("Unknown SCI version in game entry");
}
diff --git a/engines/sci/sci.h b/engines/sci/sci.h
index 82a0f80b34..a2de5c3136 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -83,19 +83,10 @@ extern const char *versionNames[7];
enum SciGameFlags {
// SCI0 flags
- /* Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2)
- * Old SCI versions used two word header for script blocks (first word equal
- * to 0x82, meaning of the second one unknown). New SCI versions used one
- * word header.
- * Also, old SCI versions assign 120 degrees to left & right, and 60 to up
- * and down. Later versions use an even 90 degree distribution.
- */
- GF_SCI0_OLD = (1 << 0),
-
/* Applies to all versions before 0.000.629
* Older SCI versions had simpler code for GetTime()
*/
- GF_SCI0_OLDGETTIME = (1 << 1)
+ GF_SCI0_OLDGETTIME = (1 << 0)
};
class SciEngine : public Engine {