aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/kernel.cpp87
-rw-r--r--engines/sci/engine/kernel.h19
-rw-r--r--engines/sci/engine/ksound.cpp2
-rw-r--r--engines/sci/engine/vm.cpp4
4 files changed, 82 insertions, 30 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index d8d5736a19..7be4c442eb 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -216,10 +216,10 @@ struct SciKernelMapSubEntry {
SciVersion fromVersion;
SciVersion toVersion;
- uint16 subNr;
+ uint16 id;
const char *name;
- KernelFunc *function;
+ KernelFunctionCall *function;
const char *signature;
const SciWorkaroundEntry *workarounds;
@@ -236,7 +236,7 @@ struct SciKernelMapSubEntry {
#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE
// SCI-Sound-Version
-#define SIG_SOUNDSCI0 SCI_VERSION_1_EARLY, SCI_VERSION_0_LATE
+#define SIG_SOUNDSCI0 SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE
#define SIG_SOUNDSCI1EARLY SCI_VERSION_1_EARLY, SCI_VERSION_1_EARLY
#define SIG_SOUNDSCI1LATE SCI_VERSION_1_LATE, SCI_VERSION_1_LATE
@@ -310,14 +310,14 @@ static const SciKernelMapSubEntry kDoSound_subops[] = {
struct SciKernelMapEntry {
const char *name;
- KernelFunc *function;
+ KernelFunctionCall *function;
SciVersion fromVersion;
SciVersion toVersion;
byte forPlatform;
const char *signature;
- const SciKernelMapSubEntry *subSignatures;
+ const SciKernelMapSubEntry *subFunctions;
const SciWorkaroundEntry *workarounds;
};
@@ -521,7 +521,7 @@ Kernel::Kernel(ResourceManager *resMan, SegManager *segMan)
}
Kernel::~Kernel() {
- for (KernelFuncsContainer::iterator i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i)
+ for (KernelFunctionArray::iterator i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i)
free(i->signature);
}
@@ -999,24 +999,26 @@ void Kernel::mapFunctions() {
_kernelFuncs.resize(functionCount);
- for (uint functNr = 0; functNr < functionCount; functNr++) {
+ for (uint id = 0; id < functionCount; id++) {
// First, get the name, if known, of the kernel function with number functnr
- Common::String sought_name = _kernelNames[functNr];
+ Common::String kernelName = _kernelNames[id];
// Reset the table entry
- _kernelFuncs[functNr].func = NULL;
- _kernelFuncs[functNr].signature = NULL;
- _kernelFuncs[functNr].origName = sought_name;
- _kernelFuncs[functNr].isDummy = true;
-
- if (sought_name.empty()) {
+ _kernelFuncs[id].function = NULL;
+ _kernelFuncs[id].signature = NULL;
+ _kernelFuncs[id].origName = kernelName;
+ _kernelFuncs[id].isDummy = true;
+ _kernelFuncs[id].workarounds = NULL;
+ _kernelFuncs[id].subFunctions = NULL;
+ _kernelFuncs[id].subFunctionCount = 0;
+ if (kernelName.empty()) {
// No name was given -> must be an unknown opcode
- warning("Kernel function %x unknown", functNr);
+ warning("Kernel function %x unknown", id);
continue;
}
// Don't map dummy functions - they will never be called
- if (sought_name == "Dummy")
+ if (kernelName == "Dummy")
continue;
// If the name is known, look it up in s_kernelMap. This table
@@ -1024,7 +1026,7 @@ void Kernel::mapFunctions() {
SciKernelMapEntry *kernelMap = s_kernelMap;
bool nameMatch = false;
while (kernelMap->name) {
- if (sought_name == kernelMap->name) {
+ if (kernelName == kernelMap->name) {
if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion <= myVersion))
if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion >= myVersion))
if (platformMask & kernelMap->forPlatform)
@@ -1037,10 +1039,49 @@ void Kernel::mapFunctions() {
if (kernelMap->name) {
// A match was found
if (kernelMap->function) {
- _kernelFuncs[functNr].func = kernelMap->function;
- _kernelFuncs[functNr].signature = parseKernelSignature(kernelMap->name, kernelMap->signature);
- _kernelFuncs[functNr].workarounds = kernelMap->workarounds;
- _kernelFuncs[functNr].isDummy = false;
+ _kernelFuncs[id].function = kernelMap->function;
+ _kernelFuncs[id].signature = parseKernelSignature(kernelMap->name, kernelMap->signature);
+ _kernelFuncs[id].workarounds = kernelMap->workarounds;
+ _kernelFuncs[id].isDummy = false;
+ if (kernelMap->subFunctions) {
+ // Get version for subfunction identification
+ SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).offset;
+ // Now check whats the highest subfunction-id for this version
+ const SciKernelMapSubEntry *kernelSubMap = kernelMap->subFunctions;
+ uint16 subFunctionCount = 0;
+ while (kernelSubMap->function) {
+ if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion))
+ if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion))
+ if (subFunctionCount <= kernelSubMap->id)
+ subFunctionCount = kernelSubMap->id + 1;
+ kernelSubMap++;
+ }
+ if (!subFunctionCount)
+ error("k%s[%x]: no subfunctions found for requested version", kernelName.c_str(), id);
+ // Now allocate required memory and go through it again
+ _kernelFuncs[id].subFunctionCount = subFunctionCount;
+ KernelSubFunction *subFunctions = new KernelSubFunction[subFunctionCount];
+ _kernelFuncs[id].subFunctions = subFunctions;
+ memset(subFunctions, 0, sizeof(KernelSubFunction) * subFunctionCount);
+ // And fill this info out
+ kernelSubMap = kernelMap->subFunctions;
+ while (kernelSubMap->function) {
+ if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion))
+ if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) {
+ uint subId = kernelSubMap->id;
+ subFunctions[subId].function = kernelSubMap->function;
+ subFunctions[subId].name = kernelSubMap->name;
+ if (kernelSubMap->signature)
+ subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature);
+ subFunctions[subId].workarounds = kernelSubMap->workarounds;
+ }
+ kernelSubMap++;
+ }
+ // Now we check, if all filled out entries got signatures
+ // If a signature is missing go through the subfunctions table again and use the last signature
+ // specified before our entry. If no signature is found at all -> bomb out
+ // TODO
+ }
++mapped;
} else {
//warning("Ignoring function %s\n", s_kernelFuncMap[found].name);
@@ -1048,9 +1089,9 @@ void Kernel::mapFunctions() {
}
} else {
if (nameMatch)
- error("kernel function %s[%x] not found for this version/platform", sought_name.c_str(), functNr);
+ error("k%s[%x]: not found for this version/platform", kernelName.c_str(), id);
// No match but a name was given -> stub
- warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functNr);
+ warning("k%s[%x]: unmapped", kernelName.c_str(), id);
}
} // for all functions requesting to be mapped
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 429a7903a1..7fa3916b31 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -118,7 +118,7 @@ enum {
// ----------------------------------------------------------------------------
/* Generic description: */
-typedef reg_t KernelFunc(EngineState *s, int argc, reg_t *argv);
+typedef reg_t KernelFunctionCall(EngineState *s, int argc, reg_t *argv);
struct SciWorkaroundEntry {
SciGameId gameId;
@@ -133,12 +133,21 @@ struct SciWorkaroundEntry {
#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, 0, NULL, NULL, -1, 0, { 0, 0 } }
-struct KernelFuncWithSignature {
- KernelFunc *func; /**< The actual function */
+struct KernelSubFunction {
+ KernelFunctionCall *function;
+ const char *name;
+ uint16 *signature;
+ const SciWorkaroundEntry *workarounds;
+};
+
+struct KernelFunction {
+ KernelFunctionCall *function;
Common::String origName; /**< Original name, in case we couldn't map it */
bool isDummy;
uint16 *signature;
const SciWorkaroundEntry *workarounds;
+ const KernelSubFunction *subFunctions;
+ uint16 subFunctionCount;
};
enum AutoDetectedFeatures {
@@ -172,8 +181,8 @@ public:
void dumpScriptClass(char *data, int seeker, int objsize);
SelectorCache _selectorCache; /**< Shortcut list for important selectors. */
- typedef Common::Array<KernelFuncWithSignature> KernelFuncsContainer;
- KernelFuncsContainer _kernelFuncs; /**< Table of kernel functions. */
+ typedef Common::Array<KernelFunction> KernelFunctionArray;
+ KernelFunctionArray _kernelFuncs; /**< Table of kernel functions. */
/**
* Determines whether a list of registers matches a given signature.
diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp
index 88b4f6a352..4ecbc523d5 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -39,6 +39,8 @@ namespace Sci {
* Used for synthesized music playback
*/
reg_t kDoSound(EngineState *s, int argc, reg_t *argv) {
+ if (!s)
+ return make_reg(0, g_sci->_features->detectDoSoundType());
return g_sci->_soundCmd->parseCommand(argc, argv, s->r_acc);
}
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index b1e6eead0e..6973694ea9 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -786,7 +786,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) {
if (kernelFuncNr >= (int)kernel->_kernelFuncs.size())
error("Invalid kernel function 0x%x requested", kernelFuncNr);
- const KernelFuncWithSignature &kernelCall = kernel->_kernelFuncs[kernelFuncNr];
+ const KernelFunction &kernelCall = kernel->_kernelFuncs[kernelFuncNr];
if (kernelCall.signature
&& !kernel->signatureMatch(kernelCall.signature, argc, s->xs->sp + 1)) {
@@ -817,7 +817,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) {
xstack->type = EXEC_STACK_TYPE_KERNEL;
// Call kernel function
- s->r_acc = kernelCall.func(s, argc, argv);
+ s->r_acc = kernelCall.function(s, argc, argv);
#if 0
// Used for debugging