[Scummvm-cvs-logs] SF.net SVN: scummvm:[50786] scummvm/trunk/engines/sci/engine

m_kiewitz at users.sourceforge.net m_kiewitz at users.sourceforge.net
Sat Jul 10 20:21:10 CEST 2010


Revision: 50786
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50786&view=rev
Author:   m_kiewitz
Date:     2010-07-10 18:21:09 +0000 (Sat, 10 Jul 2010)

Log Message:
-----------
SCI: added signatures for kGraph, removed isDummy boolean from KernelFunction

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/kernel.cpp
    scummvm/trunk/engines/sci/engine/kernel.h
    scummvm/trunk/engines/sci/engine/kgraphics.cpp
    scummvm/trunk/engines/sci/engine/vm.cpp

Modified: scummvm/trunk/engines/sci/engine/kernel.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.cpp	2010-07-10 17:08:42 UTC (rev 50785)
+++ scummvm/trunk/engines/sci/engine/kernel.cpp	2010-07-10 18:21:09 UTC (rev 50786)
@@ -199,6 +199,41 @@
 	/*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 @@
 	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 @@
     { 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 @@
     { 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 @@
 		_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 @@
 		}
 
 		// 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 @@
 			_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 @@
 				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
 

Modified: scummvm/trunk/engines/sci/engine/kernel.h
===================================================================
--- scummvm/trunk/engines/sci/engine/kernel.h	2010-07-10 17:08:42 UTC (rev 50785)
+++ scummvm/trunk/engines/sci/engine/kernel.h	2010-07-10 18:21:09 UTC (rev 50786)
@@ -141,7 +141,6 @@
 };
 
 struct KernelFunction {
-	bool isDummy;
 	KernelFunctionCall *function;
 	const char *name;
 	uint16 *signature;
@@ -491,6 +490,18 @@
 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);

Modified: scummvm/trunk/engines/sci/engine/kgraphics.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kgraphics.cpp	2010-07-10 17:08:42 UTC (rev 50785)
+++ scummvm/trunk/engines/sci/engine/kgraphics.cpp	2010-07-10 18:21:09 UTC (rev 50786)
@@ -207,128 +207,108 @@
 	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 (!s)
+		return make_reg(0, getSciVersion());
+	error("not supposed to call this");
+}
 
-	if (argc >= 5) {
-		x = argv[2].toSint16();
-		y = argv[1].toSint16();
-		x1 = argv[4].toSint16();
-		y1 = argv[3].toSint16();
-	}
+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);
+}
 
-	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;
+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_GET_COLORS_NR:
-		if (g_sci->getResMan()->isAmiga32color())
-			return make_reg(0, 32);
-		return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256);
+	// 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_DRAW_LINE:
-		priority = (argc > 6) ? argv[6].toSint16() : -1;
-		control = (argc > 7) ? argv[7].toSint16() : -1;
-		color = argv[5].toSint16();
+	g_sci->_gfxPaint16->kernelGraphDrawLine(getGraphPoint(argv), getGraphPoint(argv + 2), color, priority, control);
+	return s->r_acc;
+}
 
-		// TODO: Find out why we get >15 for color in EGA
-		if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color())
-			color &= 0x0F;
+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);
+}
 
-		g_sci->_gfxPaint16->kernelGraphDrawLine(Common::Point(x, y), Common::Point(x1, y1), color, priority, control);
-		break;
+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;
+}
 
-	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 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_RESTORE_BOX:
-		// This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX
-		g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[1]);
-		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_FILL_BOX_BACKGROUND:
-		rect = kGraphCreateRect(x, y, x1, y1);
-		g_sci->_gfxPaint16->kernelGraphFillBoxBackground(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_FILL_BOX_FOREGROUND:
-		rect = kGraphCreateRect(x, y, x1, y1);
-		g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect);
-		break;
+	g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control);
+	return s->r_acc;
+}
 
-	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 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;
+}
 
-		rect = kGraphCreateRect(x, y, x1, y1);
-		g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control);
-		break;
+reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv) {
+	Common::Rect rect = getGraphRect(argv);
+	g_sci->_gfxPaint16->kernelGraphRedrawBox(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;
-	}
-
-	case K_GRAPH_REDRAW_BOX:
-		rect = kGraphCreateRect(x, y, x1, y1);
-		g_sci->_gfxPaint16->kernelGraphRedrawBox(rect);
-		break;
-
-	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;
-
-	case K_GRAPH_SAVE_UPSCALEDHIRES_BOX:
-		rect = kGraphCreateRect(x, y, x1, y1);
-		return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect);
-
-	default:
-		error("Unsupported kGraph() operation %04x", argv[0].toSint16());
-	}
-
+// 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]);

Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp	2010-07-10 17:08:42 UTC (rev 50785)
+++ scummvm/trunk/engines/sci/engine/vm.cpp	2010-07-10 18:21:09 UTC (rev 50786)
@@ -800,50 +800,51 @@
 			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;
+	// 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);
+	// 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 @@
 		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) {


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list