SCI: part of subfunction signature&mapping implemented, little cleanup

svn-id: r50750
This commit is contained in:
Martin Kiewitz 2010-07-08 21:22:59 +00:00
parent 07fef4c6e6
commit 7e05d6e62b
4 changed files with 82 additions and 30 deletions

View File

@ -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

View File

@ -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.

View File

@ -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);
}

View File

@ -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