aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/console.cpp37
-rw-r--r--engines/sci/engine/kernel.cpp719
-rw-r--r--engines/sci/engine/kernel.h32
3 files changed, 465 insertions, 323 deletions
diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp
index bb79fc145a..7e5d77d99a 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -2042,18 +2042,18 @@ bool Console::cmdValueType(int argc, const char **argv) {
int t = g_sci->getKernel()->findRegType(val);
switch (t) {
- case KSIG_LIST:
+ case SIG_TYPE_LIST:
DebugPrintf("List");
break;
- case KSIG_OBJECT:
+ case SIG_TYPE_OBJECT:
DebugPrintf("Object");
break;
- case KSIG_REF:
+ case SIG_TYPE_REFERENCE:
DebugPrintf("Reference");
break;
- case KSIG_ARITHMETIC:
- DebugPrintf("Arithmetic");
- case KSIG_ARITHMETIC | KSIG_NULL:
+ case SIG_TYPE_INTEGER:
+ DebugPrintf("Integer");
+ case SIG_TYPE_INTEGER | SIG_TYPE_NULL:
DebugPrintf("Null");
break;
default:
@@ -2137,7 +2137,7 @@ bool Console::cmdViewReference(int argc, const char **argv) {
switch (type) {
case 0:
break;
- case KSIG_LIST: {
+ case SIG_TYPE_LIST: {
List *list = _engine->_gamestate->_segMan->lookupList(reg);
DebugPrintf("list\n");
@@ -2148,15 +2148,15 @@ bool Console::cmdViewReference(int argc, const char **argv) {
DebugPrintf("Invalid list.\n");
}
break;
- case KSIG_NODE:
+ case SIG_TYPE_NODE:
DebugPrintf("list node\n");
printNode(reg);
break;
- case KSIG_OBJECT:
+ case SIG_TYPE_OBJECT:
DebugPrintf("object\n");
printObject(reg);
break;
- case KSIG_REF: {
+ case SIG_TYPE_REFERENCE: {
switch (_engine->_gamestate->_segMan->getSegmentType(reg.segment)) {
#ifdef ENABLE_SCI32
case SEG_TYPE_STRING: {
@@ -2198,7 +2198,7 @@ bool Console::cmdViewReference(int argc, const char **argv) {
}
break;
}
- case KSIG_ARITHMETIC:
+ case SIG_TYPE_INTEGER:
DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.offset, reg.offset);
break;
default:
@@ -3149,27 +3149,30 @@ void Console::printBasicVarInfo(reg_t variable) {
int segType = g_sci->getKernel()->findRegType(variable);
SegManager *segMan = g_sci->getEngineState()->_segMan;
- segType &= KSIG_ARITHMETIC | KSIG_OBJECT | KSIG_REF | KSIG_NODE | KSIG_LIST;
+ segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED;
switch (segType) {
- case KSIG_ARITHMETIC: {
+ case SIG_TYPE_INTEGER: {
uint16 content = variable.toUint16();
if (content >= 10)
DebugPrintf(" (%dd)", content);
break;
}
- case KSIG_OBJECT:
+ case SIG_TYPE_OBJECT:
DebugPrintf(" (object '%s')", segMan->getObjectName(variable));
break;
- case KSIG_REF:
+ case SIG_TYPE_REFERENCE:
DebugPrintf(" (reference)");
break;
- case KSIG_NODE:
+ case SIG_TYPE_NODE:
DebugPrintf(" (node)");
break;
- case KSIG_LIST:
+ case SIG_TYPE_LIST:
DebugPrintf(" (list)");
break;
+ case SIG_TYPE_UNINITIALIZED:
+ DebugPrintf(" (uninitialized)");
+ break;
default:
DebugPrintf(" (??\?)");
}
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
index fb2c60cdb6..4c6fb4cf83 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -206,7 +206,7 @@ static const char *s_defaultKernelNames[] = {
// i* -> optional multiple integers
// .* -> any parameters afterwards (or none)
-// gameID, scriptNr,lvl, object-name, method-name, call,index,replace
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
static const SciWorkaroundEntry kDisposeScript_workarounds[] = {
{ GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // parameter 0 is an object when leaving graveyard
SCI_WORKAROUNDENTRY_TERMINATOR
@@ -226,6 +226,8 @@ struct SciKernelMapEntry {
};
#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE
+#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01
+#define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE
#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1
#define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1
#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE
@@ -245,129 +247,133 @@ struct SciKernelMapEntry {
// name, version/platform, signature, sub-signatures, workarounds
static SciKernelMapEntry s_kernelMap[] = {
- { MAP_CALL(Load), SIG_EVERYWHERE, "iii*", NULL, NULL },
- { MAP_CALL(UnLoad), SIG_EVERYWHERE, "iRi*", NULL, NULL },
+ { MAP_CALL(Load), SIG_EVERYWHERE, "ii(i*)", NULL, NULL },
+ { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, NULL },
// ^^ - in SQ1 when leaving ulence flats bar, kUnLoad is called with just one argument (FIXME?)
- { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL, NULL },
- { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "ii*", NULL, kDisposeScript_workarounds },
+ { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL },
+ { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "i(i*)", NULL, kDisposeScript_workarounds },
{ MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL, NULL },
{ MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL },
- { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i*", NULL, NULL },
- { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "i*", NULL, NULL },
- { MAP_CALL(Animate), SIG_EVERYWHERE, "LI*", NULL, NULL },
- // ^^ FIXME - More like (li?)?
- { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "oi*", NULL, NULL },
- // ^^ FIXME - The second parameter is ignored
+ { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL },
+ { MAP_CALL(Animate), SIG_EVERYWHERE, "(l0)(i)", NULL, NULL },
+ { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "o(i)", NULL, NULL },
{ MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL },
- { MAP_CALL(CelWide), SIG_EVERYWHERE, "iOi*", NULL, NULL },
- { MAP_CALL(CelHigh), SIG_EVERYWHERE, "iOi*", NULL, NULL },
- { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiiii*i*r*", NULL, NULL },
- { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiiii*i*", NULL, NULL },
- { MAP_CALL(AddToPic), SIG_EVERYWHERE, "Il*", NULL, NULL },
- { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, "*.", NULL, NULL },
- { MAP_CALL(NewWindow), SIG_EVERYWHERE, "iiiiZRi*", NULL, NULL },
+ { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, NULL },
+ { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, NULL },
+ { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r)", NULL, NULL },
+ { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiii(i)(i)", NULL, NULL },
+ { MAP_CALL(AddToPic), SIG_EVERYWHERE, "[il](iiiiii)", NULL, NULL },
+ { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, ".*", NULL, NULL },
+ { MAP_CALL(NewWindow), SIG_SCI0, SIGFOR_ALL, "iiii[r0]i(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(NewWindow), SIG_SCI1, SIGFOR_ALL, "iiii[ir]i(i)(i)([ir])(i)(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(NewWindow), SIG_SCI11, SIGFOR_ALL, "iiiiiiii[r0]i(i)(i)(i)", NULL, NULL },
{ MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL, NULL },
- { MAP_CALL(SetPort), SIG_EVERYWHERE, "ii*", NULL, NULL },
- { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "ii*", NULL, NULL },
+ { MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iii)(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "i(i)", NULL, NULL },
{ MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL },
- { MAP_CALL(EditControl), SIG_EVERYWHERE, "ZoZo", NULL, NULL },
- { MAP_CALL(TextSize), SIG_EVERYWHERE, "rZrii*r*", NULL, NULL },
- { MAP_CALL(Display), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "ioi*", NULL, NULL },
+ { MAP_CALL(EditControl), SIG_EVERYWHERE, "[o0][o0]", NULL, NULL },
+ { MAP_CALL(TextSize), SIG_EVERYWHERE, "r[r0]i(i)(r0)", NULL, NULL },
+ { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir]*)", NULL, NULL }, // subop
+ { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "io(i*)", NULL, NULL },
{ MAP_CALL(GetEvent), SIG_EVERYWHERE, "io", NULL, NULL },
- { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "oo*", NULL, NULL },
- { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "oo*", NULL, NULL },
+ { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL },
+ { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL },
+ { MAP_CALL(LocalToGlobal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL },
+ { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL, NULL },
- { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "oi*", NULL, NULL },
+ { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "o(i)", NULL, NULL },
{ MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL, NULL },
- { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "Zri*", NULL, NULL },
+ { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "[r0](i)(i)", NULL, NULL },
{ MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL },
- { MAP_CALL(Said), SIG_EVERYWHERE, "Zr", NULL, NULL },
+ { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL },
{ MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL },
- { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i*", NULL, NULL },
+ { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i*)", NULL, NULL },
{ MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL, NULL },
{ MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL, NULL },
{ MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL, NULL },
{ MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL, NULL },
- { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rirr*", NULL, NULL },
- { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir*", NULL, NULL },
+ { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rir(r)", NULL, NULL },
+ { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir", NULL, NULL },
{ MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL },
- { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "i*", NULL, NULL },
- { MAP_CALL(DoSound), SIG_EVERYWHERE, "iIo*", NULL, NULL },
+ { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL },
+ { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(iii)(i)", NULL, NULL }, // subop
{ MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL, NULL },
{ MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL },
{ MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL, NULL },
- { MAP_CALL(FirstNode), SIG_EVERYWHERE, "Zl", NULL, NULL },
+ { MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL },
{ MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL, NULL },
{ MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL, NULL },
{ MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL, NULL },
{ MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL },
- { MAP_CALL(NodeValue), SIG_EVERYWHERE, "Zn", NULL, NULL },
+ { MAP_CALL(NodeValue), SIG_EVERYWHERE, "[n0]", NULL, NULL },
{ MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL, NULL },
{ MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL, NULL },
{ MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL, NULL },
{ MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, NULL },
{ MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL },
- { MAP_CALL(Random), SIG_EVERYWHERE, "i*", NULL, NULL },
- { MAP_CALL(Abs), SIG_EVERYWHERE, "Oi", NULL, NULL },
+ { MAP_CALL(Random), SIG_EVERYWHERE, "ii", NULL, NULL },
+ { MAP_CALL(Abs), SIG_EVERYWHERE, "[io]", NULL, NULL },
+ // ^^ FIXME hoyle
{ MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL },
- { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiiii*", NULL, NULL },
+ { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiii", NULL, NULL },
// ^^ FIXME - occasionally KQ6 passes a 5th argument by mistake
- { MAP_CALL(GetDistance), SIG_EVERYWHERE, "iiiii*", NULL, NULL },
+ { MAP_CALL(GetDistance), SIG_EVERYWHERE, "ii(i)(i)(i)(i)", NULL, NULL },
{ MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL },
- { MAP_CALL(GetTime), SIG_EVERYWHERE, "i*", NULL, NULL },
+ { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL },
{ MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL },
- { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rri*", NULL, NULL },
- { MAP_CALL(StrLen), SIG_EVERYWHERE, "Zr", NULL, NULL },
- { MAP_CALL(StrCpy), SIG_EVERYWHERE, "rZri*", NULL, NULL },
- { MAP_CALL(Format), SIG_EVERYWHERE, "r.*", NULL, NULL },
- { MAP_CALL(GetFarText), SIG_EVERYWHERE, "iiZr", NULL, NULL },
+ { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL },
+ { MAP_CALL(StrLen), SIG_EVERYWHERE, "[r0]", NULL, NULL },
+ { MAP_CALL(StrCpy), SIG_EVERYWHERE, "[r0]r(i)", NULL, NULL },
+ { MAP_CALL(Format), SIG_EVERYWHERE, "r(.*)", NULL, NULL },
+ { MAP_CALL(GetFarText), SIG_EVERYWHERE, "ii[r0]", NULL, NULL },
{ MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL },
- { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "ol*", NULL, NULL },
- { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "ol*", NULL, NULL },
- { MAP_CALL(OnControl), SIG_EVERYWHERE, "i*", NULL, NULL },
- { MAP_CALL(InitBresen), SIG_EVERYWHERE, "oi*", NULL, NULL },
+ { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL },
+ { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL },
+ { MAP_CALL(OnControl), SIG_EVERYWHERE, "ii(i)(i)(i)", NULL, NULL },
+ { MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL },
{ MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL },
- { MAP_CALL(SetDebug), SIG_EVERYWHERE, "i*", NULL, NULL },
+ { MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL },
{ MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL, NULL },
- { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i.*", NULL, NULL },
+ { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
{ MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL },
{ MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL },
- { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r.*", NULL, NULL },
+ { MAP_CALL(CheckFreeSpace), SIG_SCI32, SIGFOR_ALL, "r.*", NULL, NULL },
+ { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r", NULL, NULL },
{ MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL },
- { MAP_CALL(CoordPri), SIG_EVERYWHERE, "ii*", NULL, NULL },
- { MAP_CALL(StrAt), SIG_EVERYWHERE, "rii*", NULL, NULL },
- { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i.*", NULL, NULL },
- { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "r*", NULL, NULL },
+ { MAP_CALL(CoordPri), SIG_EVERYWHERE, "i(i)", NULL, NULL },
+ { MAP_CALL(StrAt), SIG_EVERYWHERE, "ri(i)", NULL, NULL },
+ { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, NULL }, // subop
+ { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "(r*)", NULL, NULL },
{ MAP_CALL(GetSaveDir), SIG_EVERYWHERE, "", NULL, NULL },
{ MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "ii*", NULL, NULL },
+ { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "(i)(i)", NULL, NULL },
{ MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL },
{ MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL },
- { MAP_CALL(Graph), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(Joystick), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(FileIO), SIG_EVERYWHERE, "i.*", NULL, NULL },
- { MAP_CALL(Memory), SIG_EVERYWHERE, "i.*", NULL, NULL },
+ { MAP_CALL(Graph), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(Joystick), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(FileIO), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(Memory), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
{ MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL },
- { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii.*", NULL, NULL },
- { MAP_CALL(Lock), SIG_EVERYWHERE, "iii*", NULL, NULL },
- { MAP_CALL(Palette), SIG_EVERYWHERE, "i.*", NULL, NULL },
+ { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii(.*)", NULL, NULL },
+ { MAP_CALL(Lock), SIG_EVERYWHERE, "ii(i)", NULL, NULL },
+ { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
{ MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL, NULL },
- { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rrZr", NULL, NULL },
+ { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rr[r0]", NULL, NULL },
{ "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL, NULL },
{ "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL },
@@ -375,31 +381,31 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL, NULL },
{ MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL },
- { MAP_CALL(Message), SIG_EVERYWHERE, ".*", NULL, NULL },
+ { MAP_CALL(Message), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
{ MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL, NULL },
- { MAP_CALL(DoAudio), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(DoSync), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "iri*", NULL, NULL },
+ { MAP_CALL(DoAudio), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(DoSync), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "ir(i)", NULL, NULL }, // subop
{ MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL, NULL },
{ MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL, NULL },
- { MAP_CALL(ResCheck), SIG_EVERYWHERE, "iii*", NULL, NULL },
+ { MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL },
{ MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL },
- { MAP_CALL(ShowMovie), SIG_EVERYWHERE, ".*", NULL, NULL },
+ { MAP_CALL(ShowMovie), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL, NULL },
- { MAP_CALL(Platform), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(TextColors), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(TextFonts), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(Portrait), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(PalVary), SIG_EVERYWHERE, "ii*", NULL, NULL },
+ { MAP_CALL(Platform), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(TextColors), SIG_EVERYWHERE, "(i*)", NULL, NULL },
+ { MAP_CALL(TextFonts), SIG_EVERYWHERE, "(i*)", NULL, NULL },
+ { MAP_CALL(Portrait), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, // subop
{ MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL, NULL },
- { MAP_CALL(Empty), SIG_EVERYWHERE, ".*", NULL, NULL },
+ { MAP_CALL(Empty), SIG_EVERYWHERE, "(.*)", NULL, NULL },
#ifdef ENABLE_SCI32
// SCI2 Kernel Functions
{ MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL },
- { MAP_CALL(Array), SIG_EVERYWHERE, ".*", NULL, NULL },
+ { MAP_CALL(Array), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL, NULL },
- { MAP_CALL(String), SIG_EVERYWHERE, ".*", NULL, NULL },
+ { MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL },
@@ -409,23 +415,23 @@ static SciKernelMapEntry s_kernelMap[] = {
{ MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL },
{ MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL },
{ MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL },
- { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li.*", NULL, NULL },
- { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li.*", NULL, NULL },
- { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li.*", NULL, NULL },
- { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "lZo", NULL, NULL },
- { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio.*", NULL, NULL },
+ { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li(.*)", NULL, NULL },
+ { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL },
+ { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL },
+ { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "l[o0]", NULL, NULL },
+ { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL },
{ MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL },
- { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i.*", NULL, NULL },
+ { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
// SCI2.1 Kernel Functions
- { MAP_CALL(Save), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(List), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(Robot), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(PlayVMD), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio.*", NULL, NULL },
+ { MAP_CALL(Save), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(List), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL },
{ MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL },
- { MAP_CALL(Text), SIG_EVERYWHERE, ".*", NULL, NULL },
- { MAP_CALL(CD), SIG_EVERYWHERE, ".*", NULL, NULL },
+ { MAP_CALL(Text), SIG_EVERYWHERE, "(.*)", NULL, NULL },
+ { MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL },
{ NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL }
#endif
};
@@ -514,77 +520,349 @@ void Kernel::loadSelectorNames() {
}
}
-static char *compileKernelSignature(const char *s) {
- const char *src = s;
- char *result;
- bool ellipsis = false;
- int index = 0;
-
- if (!src)
- return 0; // NULL signature: Nothing to do
+// this parses a written kernel signature into an internal memory format
+// [io] -> either integer or object
+// (io) -> optionally integer AND an object
+// (i) -> optional integer
+// . -> any type
+// i* -> optional multiple integers
+// .* -> any parameters afterwards (or none)
+static uint16 *parseKernelSignature(const char *kernelName, const char *writtenSig) {
+ const char *curPos;
+ char curChar;
+ uint16 *result = NULL;
+ uint16 *writePos = NULL;
+ int size = 0;
+ bool validType = false;
+ bool optionalType = false;
+ bool eitherOr = false;
+ bool optional = false;
+ bool hadOptional = false;
+
+ // First, we check how many bytes the result will be
+ // we also check, if the written signature makes any sense
+ curPos = writtenSig;
+ while (*curPos) {
+ switch (*curPos) {
+ case '[': // either or
+ if (eitherOr)
+ error("signature for k%s: '[' used within '[]'", kernelName);
+ eitherOr = true;
+ validType = false;
+ break;
+ case ']': // either or end
+ if (!eitherOr)
+ error("signature for k%s: ']' used without leading '['", kernelName);
+ if (!validType)
+ error("signature for k%s: '[]' does not surround valid type(s)", kernelName);
+ eitherOr = false;
+ validType = false;
+ size++;
+ break;
+ case '(': // optional
+ if (optional)
+ error("signature for k%s: '(' used within '()' brackets", kernelName);
+ if (eitherOr)
+ error("signature for k%s: '(' used within '[]' brackets", kernelName);
+ optional = true;
+ validType = false;
+ optionalType = false;
+ break;
+ case ')': // optional end
+ if (!optional)
+ error("signature for k%s: ')' used without leading '('", kernelName);
+ if (!optionalType)
+ error("signature for k%s: '()' does not to surround valid type(s)", kernelName);
+ optional = false;
+ validType = false;
+ hadOptional = true;
+ break;
+ case '0': // allowed types
+ case 'i':
+ case 'o':
+ case 'r':
+ case 'l':
+ case 'n':
+ case '.':
+ if ((hadOptional) & (!optional))
+ error("signature for k%s: non-optional type may not follow optional type", kernelName);
+ validType = true;
+ if (optional)
+ optionalType = true;
+ if (!eitherOr)
+ size++;
+ break;
+ case '*': // accepts more of the same parameter (must be last char)
+ if (!validType) {
+ if ((writtenSig == curPos) || (*(curPos - 1) != ']'))
+ error("signature for k%s: a valid type must be in front of '*'", kernelName);
+ }
+ if (eitherOr)
+ error("signature for k%s: '*' may not be inside '[]'", kernelName);
+ if (optional) {
+ if ((*(curPos + 1) != ')') || (*(curPos + 2) != 0))
+ error("signature for k%s: '*' may only be used for last type", kernelName);
+ } else {
+ if (*(curPos + 1) != 0)
+ error("signature for k%s: '*' may only be used for last type", kernelName);
+ }
+ break;
+ default:
+ error("signature for k%s: '%c' unknown", kernelName, *curPos);
+ }
+ curPos++;
+ }
- result = (char *)malloc(strlen(s) + 1);
+ uint16 signature = 0;
+
+ // Now we allocate buffer with required size and fill it
+ result = new uint16[size + 1];
+ writePos = result;
+ curPos = writtenSig;
+ do {
+ curChar = *curPos;
+ if (!eitherOr) {
+ // not within either-or, check if next character forces output
+ switch (curChar) {
+ case 0:
+ case '[':
+ case '(':
+ case ')':
+ case 'i':
+ case 'o':
+ case 'r':
+ case 'l':
+ case 'n':
+ case '.':
+ // and we also got some signature pending?
+ if (signature) {
+ if (optional) {
+ signature |= SIG_IS_OPTIONAL;
+ if (curChar != ')')
+ signature |= SIG_NEEDS_MORE;
+ }
+ *writePos = signature;
+ writePos++;
+ signature = 0;
+ }
+ }
+ }
+ switch (curChar) {
+ case '[': // either or
+ eitherOr = true;
+ break;
+ case ']': // either or end
+ eitherOr = false;
+ break;
+ case '(': // optional
+ optional = true;
+ break;
+ case ')': // optional end
+ optional = false;
+ break;
+ case '0':
+ if (signature & SIG_TYPE_NULL)
+ error("signature for k%s: NULL specified more than once", kernelName);
+ signature |= SIG_TYPE_NULL;
+ break;
+ case 'i':
+ if (signature & SIG_TYPE_INTEGER)
+ error("signature for k%s: integer specified more than once", kernelName);
+ signature |= SIG_TYPE_INTEGER | SIG_TYPE_NULL;
+ break;
+ case 'o':
+ if (signature & SIG_TYPE_OBJECT)
+ error("signature for k%s: object specified more than once", kernelName);
+ signature |= SIG_TYPE_OBJECT;
+ break;
+ case 'r':
+ if (signature & SIG_TYPE_REFERENCE)
+ error("signature for k%s: reference specified more than once", kernelName);
+ signature |= SIG_TYPE_REFERENCE;
+ break;
+ case 'l':
+ if (signature & SIG_TYPE_LIST)
+ error("signature for k%s: list specified more than once", kernelName);
+ signature |= SIG_TYPE_LIST;
+ break;
+ case 'n':
+ if (signature & SIG_TYPE_NODE)
+ error("signature for k%s: node specified more than once", kernelName);
+ signature |= SIG_TYPE_NODE;
+ break;
+ case '.':
+ signature |= SIG_MAYBE_ANY;
+ break;
+ case '*': // accepts more of the same parameter
+ signature |= SIG_MORE_MAY_FOLLOW;
+ break;
+ default:
+ break;
+ }
+ curPos++;
+ } while (curChar);
- while (*src) {
- char c;
- char v = 0;
+ // Write terminator
+ *writePos = 0;
- if (ellipsis) {
- error("Failed compiling kernel function signature '%s': non-terminal ellipsis '%c'", s, *src);
- }
+ return result;
+}
- do {
- char cc;
- cc = c = *src++;
- if (c >= 'A' || c <= 'Z')
- cc = c | KSIG_SPEC_SUM_DONE;
+int Kernel::findRegType(reg_t reg) {
+ // No segment? Must be integer
+ if (!reg.segment)
+ return SIG_TYPE_INTEGER | (reg.offset ? 0 : SIG_TYPE_NULL);
- switch (cc) {
- case KSIG_SPEC_LIST:
- v |= KSIG_LIST;
- break;
+ if (reg.segment == 0xFFFF)
+ return SIG_TYPE_UNINITIALIZED;
- case KSIG_SPEC_NODE:
- v |= KSIG_NODE;
- break;
+ // Otherwise it's an object
+ SegmentObj *mobj = _segMan->getSegmentObj(reg.segment);
+ if (!mobj)
+ return 0; // Invalid
- case KSIG_SPEC_REF:
- v |= KSIG_REF;
- break;
+ if (!mobj->isValidOffset(reg.offset))
+ error("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg));
- case KSIG_SPEC_OBJECT:
- v |= KSIG_OBJECT;
- break;
+ switch (mobj->getType()) {
+ case SEG_TYPE_SCRIPT:
+ if (reg.offset <= (*(Script *)mobj).getBufSize() &&
+ reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET &&
+ RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) {
+ return ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE;
+ } else
+ return SIG_TYPE_REFERENCE;
+ case SEG_TYPE_CLONES:
+ return SIG_TYPE_OBJECT;
+ case SEG_TYPE_LOCALS:
+ case SEG_TYPE_STACK:
+ case SEG_TYPE_SYS_STRINGS:
+ case SEG_TYPE_DYNMEM:
+ case SEG_TYPE_HUNK:
+#ifdef ENABLE_SCI32
+ case SEG_TYPE_ARRAY:
+ case SEG_TYPE_STRING:
+#endif
+ return SIG_TYPE_REFERENCE;
+ case SEG_TYPE_LISTS:
+ return SIG_TYPE_LIST;
+ case SEG_TYPE_NODES:
+ return SIG_TYPE_NODE;
+ default:
+ return 0;
+ }
+}
- case KSIG_SPEC_ARITHMETIC:
- v |= KSIG_ARITHMETIC;
- break;
+struct SignatureDebugType {
+ uint16 typeCheck;
+ const char *text;
+};
- case KSIG_SPEC_NULL:
- v |= KSIG_NULL;
- break;
+static const SignatureDebugType signatureDebugTypeList[] = {
+ { SIG_TYPE_NULL, "null" },
+ { SIG_TYPE_INTEGER, "integer" },
+ { SIG_TYPE_UNINITIALIZED, "uninitialized" },
+ { SIG_TYPE_OBJECT, "object" },
+ { SIG_TYPE_REFERENCE, "reference" },
+ { SIG_TYPE_LIST, "list" },
+ { SIG_TYPE_NODE, "node" },
+ { 0, NULL }
+};
- case KSIG_SPEC_ANY:
- v |= KSIG_ANY;
- break;
+static void kernelSignatureDebugType(const uint16 type) {
+ bool firstPrint = true;
- case KSIG_SPEC_ELLIPSIS:
- v |= KSIG_ELLIPSIS;
- ellipsis = true;
- break;
+ const SignatureDebugType *list = signatureDebugTypeList;
+ while (list->typeCheck) {
+ if (type & list->typeCheck) {
+ if (!firstPrint)
+ printf(", ");
+ printf("%s", list->text);
+ firstPrint = false;
+ }
+ list++;
+ }
+}
- default:
- error("ERROR compiling kernel function signature '%s': (%02x / '%c') not understood", s, c, c);
+// Shows kernel call signature and current arguments for debugging purposes
+void Kernel::signatureDebug(const uint16 *sig, int argc, const reg_t *argv) {
+ int argnr = 0;
+ while (*sig || argc) {
+ printf("parameter %d: ", argnr++);
+ if (argc) {
+ reg_t parameter = *argv;
+ printf("%04x:%04x (", PRINT_REG(parameter));
+ int regType = findRegType(parameter);
+ if (regType)
+ kernelSignatureDebugType(regType);
+ else
+ printf("unknown type of %04x:%04x", PRINT_REG(parameter));
+ printf(")");
+ argv++;
+ argc--;
+ } else {
+ printf("not passed");
+ }
+ if (*sig) {
+ const uint16 signature = *sig;
+ if ((signature & SIG_MAYBE_ANY) == SIG_MAYBE_ANY) {
+ printf(", may be any");
+ } else {
+ printf(", should be ");
+ kernelSignatureDebugType(signature);
}
- } while (*src && (*src == KSIG_SPEC_ELLIPSIS || (c < 'a' && c != KSIG_SPEC_ANY)));
-
- // To handle sum types
- result[index++] = v;
+ if (signature & SIG_IS_OPTIONAL)
+ printf(" (optional)");
+ if (signature & SIG_NEEDS_MORE)
+ printf(" (needs more)");
+ if (signature & SIG_MORE_MAY_FOLLOW)
+ printf(" (more may follow)");
+ sig++;
+ }
+ printf("\n");
}
+}
- result[index] = 0;
+bool Kernel::signatureMatch(const uint16 *sig, int argc, const reg_t *argv) {
+ uint16 nextSig = *sig;
+ uint16 curSig = nextSig;
+ while (nextSig && argc) {
+ curSig = nextSig;
+ int type = findRegType(*argv);
+ if (!type)
+ return false; // couldn't determine type
- return result;
+ if (!(type & curSig))
+ return false; // type mismatch
+
+ if (!(curSig & SIG_MORE_MAY_FOLLOW)) {
+ sig++;
+ nextSig = *sig;
+ } else {
+ nextSig |= SIG_IS_OPTIONAL; // more may follow -> assumes followers are optional
+ }
+ argv++;
+ argc--;
+ }
+
+ // Too many arguments?
+ if (argc)
+ return false;
+ // Signature end reached?
+ if (nextSig == 0)
+ return true;
+ // current parameter is optional?
+ if (curSig & SIG_IS_OPTIONAL) {
+ // yes, check if nothing more is required
+ if (!(curSig & SIG_NEEDS_MORE))
+ return true;
+ } else {
+ // no, check if next parameter is optional
+ if (nextSig & SIG_IS_OPTIONAL)
+ return true;
+ }
+ // Too few arguments or more optional arguments required
+ return false;
}
void Kernel::mapFunctions() {
@@ -645,8 +923,8 @@ void Kernel::mapFunctions() {
bool nameMatch = false;
while (kernelMap->name) {
if (sought_name == kernelMap->name) {
- if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion >= myVersion))
- if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion <= myVersion))
+ if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion <= myVersion))
+ if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion >= myVersion))
if (platformMask & kernelMap->forPlatform)
break;
nameMatch = true;
@@ -658,7 +936,7 @@ void Kernel::mapFunctions() {
// A match was found
if (kernelMap->function) {
_kernelFuncs[functNr].func = kernelMap->function;
- _kernelFuncs[functNr].signature = compileKernelSignature(kernelMap->signature);
+ _kernelFuncs[functNr].signature = parseKernelSignature(kernelMap->name, kernelMap->signature);
_kernelFuncs[functNr].workarounds = kernelMap->workarounds;
_kernelFuncs[functNr].isDummy = false;
++mapped;
@@ -680,147 +958,6 @@ void Kernel::mapFunctions() {
return;
}
-int Kernel::findRegType(reg_t reg) {
- // No segment? Must be arithmetic
- if (!reg.segment)
- return reg.offset ? KSIG_ARITHMETIC : KSIG_ARITHMETIC | KSIG_NULL;
-
- if (reg.segment == 0xFFFF)
- return KSIG_UNINITIALIZED;
-
- // Otherwise it's an object
- SegmentObj *mobj = _segMan->getSegmentObj(reg.segment);
- if (!mobj)
- return 0; // Invalid
-
- if (!mobj->isValidOffset(reg.offset))
- error("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg));
-
- switch (mobj->getType()) {
- case SEG_TYPE_SCRIPT:
- if (reg.offset <= (*(Script *)mobj).getBufSize() &&
- reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET &&
- RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) {
- return ((Script *)mobj)->getObject(reg.offset) ? KSIG_OBJECT : KSIG_REF;
- } else
- return KSIG_REF;
- case SEG_TYPE_CLONES:
- return KSIG_OBJECT;
- case SEG_TYPE_LOCALS:
- case SEG_TYPE_STACK:
- case SEG_TYPE_SYS_STRINGS:
- case SEG_TYPE_DYNMEM:
- case SEG_TYPE_HUNK:
-#ifdef ENABLE_SCI32
- case SEG_TYPE_ARRAY:
- case SEG_TYPE_STRING:
-#endif
- return KSIG_REF;
- case SEG_TYPE_LISTS:
- return KSIG_LIST;
- case SEG_TYPE_NODES:
- return KSIG_NODE;
- default:
- return 0;
- }
-}
-
-struct SignatureDebugType {
- char typeCheck;
- const char *text;
-};
-
-static const SignatureDebugType signatureDebugTypeList[] = {
- { KSIG_NULL, "null" },
- { KSIG_ARITHMETIC, "value" },
- { KSIG_UNINITIALIZED, "uninitialized" },
- { KSIG_OBJECT, "object" },
- { KSIG_REF, "reference" },
- { KSIG_LIST, "list" },
- { KSIG_NODE, "node" },
- { 0, NULL }
-};
-
-static void kernelSignatureDebugType(const char type) {
- bool firstPrint = true;
-
- const SignatureDebugType *list = signatureDebugTypeList;
- while (list->typeCheck) {
- if (type & list->typeCheck) {
- if (!firstPrint)
- printf(", ");
- printf("%s", list->text);
- firstPrint = false;
- }
- list++;
- }
-}
-
-// Shows kernel call signature and current arguments for debugging purposes
-void Kernel::signatureDebug(const char *sig, int argc, const reg_t *argv) {
- int argnr = 0;
- while (*sig || argc) {
- printf("parameter %d: ", argnr++);
- if (argc) {
- reg_t parameter = *argv;
- printf("%04x:%04x (", PRINT_REG(parameter));
- int regType = findRegType(parameter);
- if (regType)
- kernelSignatureDebugType(regType);
- else
- printf("unknown type of %04x:%04x", PRINT_REG(parameter));
- printf(")");
- argv++;
- argc--;
- } else {
- printf("not passed");
- }
- if (*sig) {
- const char signature = *sig;
- if ((signature & KSIG_ANY) == KSIG_ANY) {
- printf(", may be any");
- } else {
- printf(", should be ");
- kernelSignatureDebugType(signature);
- }
- if (signature & KSIG_ELLIPSIS)
- printf(" (optional)");
- sig++;
- }
- printf("\n");
- }
-}
-
-bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) {
- // Always "match" if no signature is given
- if (!sig)
- return true;
-
- while (*sig && argc) {
- if ((*sig & KSIG_ANY) != KSIG_ANY) {
- int type = findRegType(*argv);
-
- if (!type)
- return false; // couldn't determine type
-
- if (!(type & *sig))
- return false; // type mismatch
-
- }
- if (!(*sig & KSIG_ELLIPSIS))
- ++sig;
- ++argv;
- --argc;
- }
-
- if (argc)
- return false; // Too many arguments
- if (*sig == 0 || (*sig & KSIG_ELLIPSIS))
- return true;
-
- return false; // Too few arguments
-}
-
void Kernel::setDefaultKernelNames() {
_kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames));
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 9b4a11f132..ef587194d6 100644
--- a/engines/sci/engine/kernel.h
+++ b/engines/sci/engine/kernel.h
@@ -96,20 +96,23 @@ struct SelectorCache; // from selector.h
// ---- Kernel signatures -----------------------------------------------------
-
-// Compiled signatures
+// internal kernel signature data
enum {
- KSIG_LIST = 0x01,
- KSIG_NODE = 0x02,
- KSIG_OBJECT = 0x04,
- KSIG_REF = 0x08,
- KSIG_ARITHMETIC = 0x10,
- KSIG_UNINITIALIZED = 0x20,
- KSIG_NULL = 0x40,
- KSIG_ANY = 0x5f,
- KSIG_ELLIPSIS = 0x80
+ SIG_TYPE_NULL = 0x01, // may be 0:0 [0]
+ SIG_TYPE_INTEGER = 0x02, // may be 0:* [i], automatically also allows null
+ SIG_TYPE_UNINITIALIZED = 0x04, // may be FFFF:* -> not allowable, only used for comparsion
+ SIG_TYPE_OBJECT = 0x10, // may be object [o]
+ SIG_TYPE_REFERENCE = 0x20, // may be reference [r]
+ SIG_TYPE_LIST = 0x40, // may be list [l]
+ SIG_TYPE_NODE = 0x80, // may be node [n]
+ SIG_IS_OPTIONAL = 0x100, // is optional
+ SIG_NEEDS_MORE = 0x200, // needs at least one additional parameter following
+ SIG_MORE_MAY_FOLLOW = 0x400, // may have more parameters of the same type following
};
+// this does not include SIG_TYPE_UNINITIALIZED, because we can not allow uninitialized values anywhere
+#define SIG_MAYBE_ANY (SIG_TYPE_NULL | SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_LIST | SIG_TYPE_NODE)
+
// ----------------------------------------------------------------------------
/* Generic description: */
@@ -132,7 +135,7 @@ struct KernelFuncWithSignature {
KernelFunc *func; /**< The actual function */
Common::String origName; /**< Original name, in case we couldn't map it */
bool isDummy;
- char *signature;
+ uint16 *signature;
const SciWorkaroundEntry *workarounds;
};
@@ -175,16 +178,15 @@ public:
* If no signature is given (i.e., if sig is NULL), this is always
* treated as a match.
*
- * @param segMan pointer to the segment manager
* @param sig signature to test against
* @param argc number of arguments to test
* @param argv argument list
* @return true if the signature was matched, false otherwise
*/
- bool signatureMatch(const char *sig, int argc, const reg_t *argv);
+ bool signatureMatch(const uint16 *sig, int argc, const reg_t *argv);
// Prints out debug information in case a signature check fails
- void signatureDebug(const char *sig, int argc, const reg_t *argv);
+ void signatureDebug(const uint16 *sig, int argc, const reg_t *argv);
/**
* Determines the type of the object indicated by reg.