aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorMartin Kiewitz2010-07-10 18:21:09 +0000
committerMartin Kiewitz2010-07-10 18:21:09 +0000
commit790e9b0351a043d2d5e4c048a081f5f6ab24c9a9 (patch)
tree42e272405c8c2970ed1a53ea4bef49c685ed2ce6 /engines/sci
parentb7906e7feb33cf1b31433f9962bb02b393e1943e (diff)
downloadscummvm-rg350-790e9b0351a043d2d5e4c048a081f5f6ab24c9a9.tar.gz
scummvm-rg350-790e9b0351a043d2d5e4c048a081f5f6ab24c9a9.tar.bz2
scummvm-rg350-790e9b0351a043d2d5e4c048a081f5f6ab24c9a9.zip
SCI: added signatures for kGraph, removed isDummy boolean from KernelFunction
svn-id: r50786
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/engine/kernel.cpp67
-rw-r--r--engines/sci/engine/kernel.h13
-rw-r--r--engines/sci/engine/kgraphics.cpp178
-rw-r--r--engines/sci/engine/vm.cpp107
4 files changed, 197 insertions, 168 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index 2fb1452fa2..0fd21671a0 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -199,6 +199,41 @@ static const char *s_defaultKernelNames[] = {
/*0x88*/ "Dummy" // DbugStr
};
+reg_t kStub(EngineState *s, int argc, reg_t *argv) {
+ Kernel *kernel = g_sci->getKernel();
+ int kernelCallNr = -1;
+
+ Common::List<ExecStack>::iterator callIterator = s->_executionStack.end();
+ if (callIterator != s->_executionStack.begin()) {
+ callIterator--;
+ ExecStack lastCall = *callIterator;
+ kernelCallNr = lastCall.debugSelector;
+ }
+
+ Common::String warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr) +
+ Common::String::printf("[%x]", kernelCallNr) +
+ " invoked. Params: " +
+ Common::String::printf("%d", argc) + " (";
+
+ for (int i = 0; i < argc; i++) {
+ warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i]));
+ warningMsg += (i == argc - 1 ? ")" : ", ");
+ }
+
+ warning("%s", warningMsg.c_str());
+ return s->r_acc;
+}
+
+reg_t kStubNull(EngineState *s, int argc, reg_t *argv) {
+ kStub(s, argc, argv);
+ return NULL_REG;
+}
+
+reg_t kDummy(EngineState *s, int argc, reg_t *argv) {
+ kStub(s, argc, argv);
+ error("Kernel function was called, which was considered to be unused - see log for details");
+}
+
// [io] -> either integer or object
// (io) -> optionally integer AND an object
// (i) -> optional integer
@@ -308,6 +343,26 @@ static const SciKernelMapSubEntry kDoSound_subops[] = {
SCI_SUBOPENTRY_TERMINATOR
};
+static const SciKernelMapSubEntry kGraph_subops[] = {
+ { SIG_SCI32, 1, MAP_CALL(StubNull), "", NULL }, // called by gk1 sci32 right at the start
+ { SIG_SCIALL, 2, MAP_CALL(GraphGetColorCount), "", NULL },
+ // 3 - set palette via resource
+ { SIG_SCIALL, 4, MAP_CALL(GraphDrawLine), "iiiii(i)(i)", NULL },
+ // 5 - nop
+ // 6 - draw pattern
+ { SIG_SCIALL, 7, MAP_CALL(GraphSaveBox), "iiiii", NULL },
+ { SIG_SCIALL, 8, MAP_CALL(GraphRestoreBox), "[r0!]", NULL },
+ // ^ this may get called with invalid references, we check them within restoreBits() and sierra sci behaves the same
+ { SIG_SCIALL, 9, MAP_CALL(GraphFillBoxBackground), "iiii", NULL },
+ { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", NULL },
+ { SIG_SCIALL, 11, MAP_CALL(GraphFillBoxAny), "iiiiii(i)(i)", NULL },
+ { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)(r)", NULL },
+ { SIG_SCIALL, 13, MAP_CALL(GraphRedrawBox), "iiii", NULL },
+ { SIG_SCIALL, 14, MAP_CALL(GraphAdjustPriority), "ii", NULL },
+ { SIG_SCI11, 15, MAP_CALL(GraphSaveUpscaledHiresBox), "iiii", NULL }, // kq6 hires
+ SCI_SUBOPENTRY_TERMINATOR
+};
+
static const SciKernelMapSubEntry kPalVary_subops[] = {
{ SIG_SCIALL, 0, MAP_CALL(PalVaryInit), "ii(i)(i)", NULL },
{ SIG_SCIALL, 1, MAP_CALL(PalVaryReverse), "(i)(i)(i)", NULL },
@@ -372,6 +427,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, NULL }, // subop
{ MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir!]*)", NULL, NULL },
// ^ we allow invalid references here, because kDisplay gets called with those in e.g. pq3 during intro
+ // restoreBits() checks and skips invalid handles, so that's fine. Sierra SCI behaved the same
{ MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL },
{ MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL },
@@ -417,9 +473,7 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL },
{ MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL },
{ MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL },
- { MAP_CALL(Graph), SIG_EVERYWHERE, "i([!.]*)", NULL, NULL }, // subop
- // ^^ we allow invalid references here, because kGraph(restoreBox) gets called with old non-existant handles often
- // this should get limited to this call only as soon as subop signatures are available
+ { MAP_CALL(Graph), SIG_EVERYWHERE, "i([!.]*)", kGraph_subops, NULL },
{ MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL },
{ MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL },
@@ -1032,7 +1086,6 @@ void Kernel::mapFunctions() {
_kernelFuncs[id].function = NULL;
_kernelFuncs[id].signature = NULL;
_kernelFuncs[id].name = NULL;
- _kernelFuncs[id].isDummy = true;
_kernelFuncs[id].workarounds = NULL;
_kernelFuncs[id].subFunctions = NULL;
_kernelFuncs[id].subFunctionCount = 0;
@@ -1044,8 +1097,10 @@ void Kernel::mapFunctions() {
}
// Don't map dummy functions - they will never be called
- if (kernelName == "Dummy")
+ if (kernelName == "Dummy") {
+ _kernelFuncs[id].function = kDummy;
continue;
+ }
// If the name is known, look it up in s_kernelMap. This table
// maps kernel func names to actual function (pointers).
@@ -1068,7 +1123,6 @@ void Kernel::mapFunctions() {
_kernelFuncs[id].name = kernelMap->name;
_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;
@@ -1129,6 +1183,7 @@ void Kernel::mapFunctions() {
error("k%s[%x]: not found for this version/platform", kernelName.c_str(), id);
// No match but a name was given -> stub
warning("k%s[%x]: unmapped", kernelName.c_str(), id);
+ _kernelFuncs[id].function = kStub;
}
} // for all functions requesting to be mapped
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 5815fec53b..a054aa2b1c 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -141,7 +141,6 @@ struct KernelSubFunction {
};
struct KernelFunction {
- bool isDummy;
KernelFunctionCall *function;
const char *name;
uint16 *signature;
@@ -491,6 +490,18 @@ reg_t kDoSoundSetVolume(EngineState *s, int argc, reg_t *argv);
reg_t kDoSoundSetPriority(EngineState *s, int argc, reg_t *argv);
reg_t kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphSaveBox(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphRestoreBox(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphFillBoxBackground(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphUpdateBox(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphAdjustPriority(EngineState *s, int argc, reg_t *argv);
+reg_t kGraphSaveUpscaledHiresBox(EngineState *s, int argc, reg_t *argv);
+
reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv);
reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv);
reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv);
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index 9714374ade..0e7930275a 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -207,128 +207,108 @@ reg_t kPicNotValid(EngineState *s, int argc, reg_t *argv) {
return make_reg(0, g_sci->_gfxScreen->kernelPicNotValid(newPicNotValid));
}
-Common::Rect kGraphCreateRect(int16 x, int16 y, int16 x1, int16 y1) {
+static Common::Rect getGraphRect(reg_t *argv) {
+ int16 x = argv[1].toSint16();
+ int16 y = argv[0].toSint16();
+ int16 x1 = argv[3].toSint16();
+ int16 y1 = argv[2].toSint16();
if (x > x1) SWAP(x, x1);
if (y > y1) SWAP(y, y1);
return Common::Rect(x, y, x1, y1);
}
-// Graph subfunctions
-enum {
- K_GRAPH_GET_COLORS_NR = 2,
- // 3 - SET PALETTE VIA RESOURCE
- K_GRAPH_DRAW_LINE = 4,
- // 5 - NOP
- // 6 - DRAW PATTERN
- K_GRAPH_SAVE_BOX = 7,
- K_GRAPH_RESTORE_BOX = 8,
- K_GRAPH_FILL_BOX_BACKGROUND = 9,
- K_GRAPH_FILL_BOX_FOREGROUND = 10,
- K_GRAPH_FILL_BOX_ANY = 11,
- K_GRAPH_UPDATE_BOX = 12,
- K_GRAPH_REDRAW_BOX = 13,
- K_GRAPH_ADJUST_PRIORITY = 14,
- K_GRAPH_SAVE_UPSCALEDHIRES_BOX = 15 // KQ6CD Windows version
-};
+static Common::Point getGraphPoint(reg_t *argv) {
+ int16 x = argv[1].toSint16();
+ int16 y = argv[0].toSint16();
+ return Common::Point(x, y);
+}
reg_t kGraph(EngineState *s, int argc, reg_t *argv) {
- int16 x = 0, y = 0, x1 = 0, y1 = 0;
- uint16 screenMask;
- int16 priority, control, color, colorMask;
- Common::Rect rect;
-
- if (argc >= 5) {
- x = argv[2].toSint16();
- y = argv[1].toSint16();
- x1 = argv[4].toSint16();
- y1 = argv[3].toSint16();
- }
-
- switch (argv[0].toSint16()) {
- case 1:
- // TODO: Happens in GK1CD, right when it starts
- warning("Unsupported kGraph() operation %04x", argv[0].toSint16());
- // Returns an integer
- return SIGNAL_REG;
-
- case K_GRAPH_GET_COLORS_NR:
- if (g_sci->getResMan()->isAmiga32color())
- return make_reg(0, 32);
- return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256);
-
- case K_GRAPH_DRAW_LINE:
- priority = (argc > 6) ? argv[6].toSint16() : -1;
- control = (argc > 7) ? argv[7].toSint16() : -1;
- color = argv[5].toSint16();
-
- // TODO: Find out why we get >15 for color in EGA
- if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color())
- color &= 0x0F;
+ if (!s)
+ return make_reg(0, getSciVersion());
+ error("not supposed to call this");
+}
- g_sci->_gfxPaint16->kernelGraphDrawLine(Common::Point(x, y), Common::Point(x1, y1), color, priority, control);
- break;
+reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isAmiga32color())
+ return make_reg(0, 32);
+ return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256);
+}
- case K_GRAPH_SAVE_BOX:
- rect = kGraphCreateRect(x, y, x1, y1);
- screenMask = (argc > 5) ? argv[5].toUint16() : 0;
- return g_sci->_gfxPaint16->kernelGraphSaveBox(rect, screenMask);
+reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv) {
+ int16 color = argv[4].toSint16();
+ int16 priority = (argc > 5) ? argv[5].toSint16() : -1;
+ int16 control = (argc > 6) ? argv[6].toSint16() : -1;
- case K_GRAPH_RESTORE_BOX:
- // This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX
- g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[1]);
- break;
+ // TODO: Find out why we get >15 for color in EGA
+ if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color())
+ color &= 0x0F;
- case K_GRAPH_FILL_BOX_BACKGROUND:
- rect = kGraphCreateRect(x, y, x1, y1);
- g_sci->_gfxPaint16->kernelGraphFillBoxBackground(rect);
- break;
+ g_sci->_gfxPaint16->kernelGraphDrawLine(getGraphPoint(argv), getGraphPoint(argv + 2), color, priority, control);
+ return s->r_acc;
+}
- case K_GRAPH_FILL_BOX_FOREGROUND:
- rect = kGraphCreateRect(x, y, x1, y1);
- g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect);
- break;
+reg_t kGraphSaveBox(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ uint16 screenMask = (argc > 4) ? argv[4].toUint16() : 0;
+ return g_sci->_gfxPaint16->kernelGraphSaveBox(rect, screenMask);
+}
- case K_GRAPH_FILL_BOX_ANY:
- priority = (argc > 7) ? argv[7].toSint16() : -1;
- control = (argc > 8) ? argv[8].toSint16() : -1;
- color = argv[6].toSint16();
- colorMask = argv[5].toUint16();
+reg_t kGraphRestoreBox(EngineState *s, int argc, reg_t *argv) {
+ // This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX
+ g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[0]);
+ return s->r_acc;
+}
- rect = kGraphCreateRect(x, y, x1, y1);
- g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control);
- break;
+reg_t kGraphFillBoxBackground(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ g_sci->_gfxPaint16->kernelGraphFillBoxBackground(rect);
+ return s->r_acc;
+}
- case K_GRAPH_UPDATE_BOX: {
- rect = kGraphCreateRect(x, y, x1, y1);
- bool hiresMode = (argc > 6) ? true : false;
- // arg5 is the map (1 for visual, etc.)
- // argc == 7 on upscaled hires
- g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode);
- break;
- }
+reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect);
+ return s->r_acc;
+}
- case K_GRAPH_REDRAW_BOX:
- rect = kGraphCreateRect(x, y, x1, y1);
- g_sci->_gfxPaint16->kernelGraphRedrawBox(rect);
- break;
+reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ int16 colorMask = argv[4].toUint16();
+ int16 color = argv[5].toSint16();
+ int16 priority = (argc > 6) ? argv[6].toSint16() : -1;
+ int16 control = (argc > 7) ? argv[7].toSint16() : -1;
- case K_GRAPH_ADJUST_PRIORITY:
- // Seems to be only implemented for SCI0/SCI01 games
- debugC(2, kDebugLevelGraphics, "adjust_priority(%d, %d)", argv[1].toUint16(), argv[2].toUint16());
- g_sci->_gfxPorts->kernelGraphAdjustPriority(argv[1].toUint16(), argv[2].toUint16());
- break;
+ g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control);
+ return s->r_acc;
+}
- case K_GRAPH_SAVE_UPSCALEDHIRES_BOX:
- rect = kGraphCreateRect(x, y, x1, y1);
- return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect);
+reg_t kGraphUpdateBox(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ // argv[4] is the map (1 for visual, etc.)
+ // argc == 6 on upscaled hires
+ bool hiresMode = (argc > 5) ? true : false;
+ g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode);
+ return s->r_acc;
+}
- default:
- error("Unsupported kGraph() operation %04x", argv[0].toSint16());
- }
+reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ g_sci->_gfxPaint16->kernelGraphRedrawBox(rect);
+ return s->r_acc;
+}
+// Seems to be only implemented for SCI0/SCI01 games
+reg_t kGraphAdjustPriority(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxPorts->kernelGraphAdjustPriority(argv[0].toUint16(), argv[1].toUint16());
return s->r_acc;
}
+reg_t kGraphSaveUpscaledHiresBox(EngineState *s, int argc, reg_t *argv) {
+ Common::Rect rect = getGraphRect(argv);
+ return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect);
+}
+
reg_t kTextSize(EngineState *s, int argc, reg_t *argv) {
int16 textWidth, textHeight;
Common::String text = s->_segMan->getString(argv[1]);
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index a354491a83..cbfaf5575f 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -800,50 +800,51 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
return;
}
- if (!kernelCall.isDummy) {
- // Add stack frame to indicate we're executing a callk.
- // This is useful in debugger backtraces if this
- // kernel function calls a script itself.
- ExecStack *xstack;
- xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG,
- s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
- xstack->debugSelector = kernelCallNr;
- xstack->type = EXEC_STACK_TYPE_KERNEL;
-
- // Call kernel function
- if (!kernelCall.subFunctionCount) {
- s->r_acc = kernelCall.function(s, argc, argv);
- } else {
- // Sub-functions available, check signature and call that one directly
- if (argc < 1)
- error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr);
- const uint16 subId = argv[0].toUint16();
- // Skip over subfunction-id
- argc--;
- argv++;
- if (subId >= kernelCall.subFunctionCount)
- error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId);
- const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId];
- if (!kernel->signatureMatch(kernelSubCall.signature, argc, argv)) {
- // Signature mismatch
- SciTrackOriginReply originReply;
- reg_t workaround;
- workaround = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply);
- if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) {
- kernel->signatureDebug(kernelSubCall.signature, argc, argv);
- int callNameLen = strlen(kernelCall.name);
- if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) {
- const char *subCallName = kernelSubCall.name + callNameLen;
- error("[VM] k%s(%s): signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
- }
- error("[VM] k%s: signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
+ // Add stack frame to indicate we're executing a callk.
+ // This is useful in debugger backtraces if this
+ // kernel function calls a script itself.
+ ExecStack *xstack;
+ xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG,
+ s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
+ xstack->debugSelector = kernelCallNr;
+ xstack->type = EXEC_STACK_TYPE_KERNEL;
+
+ // Call kernel function
+ if (!kernelCall.subFunctionCount) {
+ s->r_acc = kernelCall.function(s, argc, argv);
+ } else {
+ // Sub-functions available, check signature and call that one directly
+ if (argc < 1)
+ error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr);
+ const uint16 subId = argv[0].toUint16();
+ // Skip over subfunction-id
+ argc--;
+ argv++;
+ if (subId >= kernelCall.subFunctionCount)
+ error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId);
+ const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId];
+ if (kernelSubCall.signature && !kernel->signatureMatch(kernelSubCall.signature, argc, argv)) {
+ // Signature mismatch
+ SciTrackOriginReply originReply;
+ reg_t workaround;
+ workaround = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply);
+ if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) {
+ kernel->signatureDebug(kernelSubCall.signature, argc, argv);
+ int callNameLen = strlen(kernelCall.name);
+ if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) {
+ const char *subCallName = kernelSubCall.name + callNameLen;
+ error("[VM] k%s(%s): signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
}
- // FIXME: implement some real workaround type logic - ignore call, still do call etc.
- if (workaround.segment)
- return;
+ error("[VM] k%s: signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
}
- s->r_acc = kernelSubCall.function(s, argc, argv);
+ // FIXME: implement some real workaround type logic - ignore call, still do call etc.
+ if (workaround.segment)
+ return;
}
+ if (!kernelSubCall.function)
+ error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId);
+ s->r_acc = kernelSubCall.function(s, argc, argv);
+ }
#if 0
// Used for debugging
@@ -861,27 +862,9 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
debug("%s", debugMsg.c_str());
#endif
- // Remove callk stack frame again, if there's still an execution stack
- if (s->_executionStack.begin() != s->_executionStack.end())
- s->_executionStack.pop_back();
- } else {
- Common::String warningMsg = "Dummy function " + kernel->getKernelName(kernelCallNr) +
- Common::String::printf("[0x%x]", kernelCallNr) +
- " invoked - ignoring. Params: " +
- Common::String::printf("%d", argc) + " (";
-
- for (int i = 0; i < argc; i++) {
- warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i]));
- warningMsg += (i == argc - 1 ? ")" : ", ");
- }
-
- warning("%s", warningMsg.c_str());
-
- // Make sure that the game doesn't call a function that is considered unused. If
- // that happens, error out.
- if (kernel->getKernelName(kernelCallNr) == "Dummy")
- error("Kernel function %d was called, which was considered to be unused", kernelCallNr);
- }
+ // Remove callk stack frame again, if there's still an execution stack
+ if (s->_executionStack.begin() != s->_executionStack.end())
+ s->_executionStack.pop_back();
}
static void gcCountDown(EngineState *s) {