aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/kernel.cpp')
-rw-r--r--engines/sci/engine/kernel.cpp1093
1 files changed, 1093 insertions, 0 deletions
diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp
new file mode 100644
index 0000000000..7498d9763b
--- /dev/null
+++ b/engines/sci/engine/kernel.cpp
@@ -0,0 +1,1093 @@
+/***************************************************************************
+ kernel.c Copyright (C) 1999 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CJR) [jameson@linuxgames.com]
+
+***************************************************************************/
+
+#include "sci/engine/gc.h"
+#include "sci/include/sciresource.h"
+#include "sci/include/engine.h"
+#ifdef _WIN32
+# include <windows.h>
+# include <mmsystem.h>
+#endif
+
+#include "sci/include/gfx_operations.h"
+#include "sci/engine/kernel_types.h"
+
+
+/* New kernel functions */
+reg_t kStrLen(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGetFarText(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kReadNumber(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kStrCat(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kStrCmp(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSetSynonyms(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kLock(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kPalette(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kNumCels(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kNumLoops(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDrawCel(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kCoordPri(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kPriCoord(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kShakeScreen(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSetCursor(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kMoveCursor(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kShow(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kPicNotValid(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kOnControl(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDrawPic(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGetPort(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSetPort(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kNewWindow(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDisposeWindow(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kCelWide(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kCelHigh(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSetJump(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDirLoop(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDoAvoider(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGetAngle(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGetDistance(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kRandom(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kAbs(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSqrt(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kTimesSin(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kTimesCos(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kCosMult(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSinMult(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kTimesTan(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kTimesCot(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kCosDiv(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSinDiv(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kValidPath(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFOpen(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFPuts(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFGets(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFClose(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kMapKeyToDir(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGlobalToLocal(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kLocalToGlobal(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kWait(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kRestartGame(struct _state *s, int funct_nr, int argc, reg_t *argv);
+#ifdef _WIN32
+reg_t kDeviceInfo_Win32(struct _state *s, int funct_nr, int argc, reg_t *argv);
+#else
+reg_t kDeviceInfo_Unix(struct _state *s, int funct_nr, int argc, reg_t *argv);
+#endif
+reg_t kGetEvent(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kCheckFreeSpace(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFlushResources(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGetSaveFiles(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSetDebug(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kCheckSaveGame(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSaveGame(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kRestoreGame(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFileIO(struct _state *s, int funct_nr, int argc, reg_t *argp);
+reg_t kGetTime(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kHaveMouse(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kJoystick(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGameIsRestarting(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGetCWD(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSort(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kStrEnd(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kMemory(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kAvoidPath(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kParse(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSaid(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kStrCpy(struct _state *s, int funct_nr, int argc, reg_t *argp);
+reg_t kStrAt(struct _state *s, int funct_nr, int argc, reg_t *argp);
+reg_t kEditControl(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDrawControl(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kHiliteControl(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kClone(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDisposeClone(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kCanBeHere(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSetNowSeen(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kInitBresen(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDoBresen(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kBaseSetter(struct _state *s, int funct_nr, int argc, reg_t *argp);
+reg_t kAddToPic(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kAnimate(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDisplay(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGraph(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFormat(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDoSound(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kAddMenu(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kSetMenu(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGetMenu(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDrawStatus(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDrawMenuBar(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kMenuSelect(struct _state *s, int funct_nr, int argc, reg_t *argv);
+
+reg_t kLoad(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kUnLoad(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kScriptID(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDisposeScript(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kIsObject(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kRespondsTo(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kNewList(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDisposeList(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kNewNode(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFirstNode(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kLastNode(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kEmptyList(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kNextNode(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kPrevNode(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kNodeValue(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kAddAfter(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kAddToFront(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kAddToEnd(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kFindKey(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDeleteKey(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kMemoryInfo(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kGetSaveDir(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kTextSize(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kIsItSkip(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kMessage(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t kDoAudio(struct _state *s, int funct_nr, int argc, reg_t *argv);
+reg_t k_Unknown(struct _state *s, int funct_nr, int argc, reg_t *argv);
+
+/* The Unknown/Unnamed kernel function */
+reg_t kstub(struct _state *s, int funct_nr, int argc, reg_t *argv);
+/* for unimplemented kernel functions */
+reg_t kNOP(struct _state *s, int funct_nr, int argc, reg_t *argv);
+/* for kernel functions that don't do anything */
+reg_t kFsciEmu(struct _state *s, int funct_nr, int argc, reg_t *argv);
+/* Emulating "old" kernel functions on the heap */
+
+
+#define SCI_MAPPED_UNKNOWN_KFUNCTIONS_NR 0x75
+/* kfunct_mappers below doubles for unknown kfunctions */
+
+static int sci_max_allowed_unknown_kernel_functions[] = {
+ 0,
+ 0x72, /* SCI0 */
+ 0x7b, /* SCI01/EGA */
+ 0x7b, /* SCI01/VGA */
+ 0x7b, /* SCI1/EARLY */
+ 0x7b, /* SCI1/LATE */
+ 0x7b, /* SCI1.1 */
+ 0x0, /* SCI32 */
+};
+
+#define DEFUN(nm, cname, sig) {KF_NEW, nm, {cname, sig, NULL}}
+#define NOFUN(nm) {KF_NONE, nm, {NULL, NULL, NULL}}
+
+sci_kernel_function_t kfunct_mappers[] = {
+/*00*/ DEFUN("Load", kLoad, "iii*"),
+/*01*/ DEFUN("UnLoad", kUnLoad, "i.*"),
+/*02*/ DEFUN("ScriptID", kScriptID, "Ioi*"),
+/*03*/ DEFUN("DisposeScript", kDisposeScript, "Oi"), /* Work around QfG1 bug */
+/*04*/ DEFUN("Clone", kClone, "o"),
+/*05*/ DEFUN("DisposeClone", kDisposeClone, "o"),
+/*06*/ DEFUN("IsObject", kIsObject, "."),
+/*07*/ DEFUN("RespondsTo", kRespondsTo, ".i"),
+/*08*/ DEFUN("DrawPic", kDrawPic, "i*"),
+/*09*/ DEFUN("Show", kShow, "i"),
+/*0a*/ DEFUN("PicNotValid", kPicNotValid, "i*"),
+/*0b*/ DEFUN("Animate", kAnimate, "LI*"), /* More like (li?)? */
+/*0c*/ DEFUN("SetNowSeen", kSetNowSeen, "oi*"), /* The second parameter is ignored */
+/*0d*/ DEFUN("NumLoops", kNumLoops, "o"),
+/*0e*/ DEFUN("NumCels", kNumCels, "o"),
+/*0f*/ DEFUN("CelWide", kCelWide, "iOiOi"),
+/*10*/ DEFUN("CelHigh", kCelHigh, "iOiOi"),
+/*11*/ DEFUN("DrawCel", kDrawCel, "iiiiii*"),
+/*12*/ DEFUN("AddToPic", kAddToPic, "Il*"),
+/*13*/ DEFUN("NewWindow", kNewWindow, "iiiiZRi*"),
+/*14*/ DEFUN("GetPort", kGetPort, ""),
+/*15*/ DEFUN("SetPort", kSetPort, "ii*"),
+/*16*/ DEFUN("DisposeWindow", kDisposeWindow, "ii*"),
+/*17*/ DEFUN("DrawControl", kDrawControl, "o"),
+/*18*/ DEFUN("HiliteControl", kHiliteControl, "o"),
+/*19*/ DEFUN("EditControl", kEditControl, "ZoZo"),
+/*1a*/ DEFUN("TextSize", kTextSize, "rZrii*r*"),
+/*1b*/ DEFUN("Display", kDisplay, ".*"),
+/*1c*/ DEFUN("GetEvent", kGetEvent, "io"),
+/*1d*/ DEFUN("GlobalToLocal", kGlobalToLocal, "o"),
+/*1e*/ DEFUN("LocalToGlobal", kLocalToGlobal, "o"),
+/*1f*/ DEFUN("MapKeyToDir", kMapKeyToDir, "o"),
+/*20*/ DEFUN("DrawMenuBar", kDrawMenuBar, "i"),
+/*21*/ DEFUN("MenuSelect", kMenuSelect, "oi*"),
+/*22*/ DEFUN("AddMenu", kAddMenu, "rr"),
+/*23*/ DEFUN("DrawStatus", kDrawStatus, "Zri*"),
+/*24*/ DEFUN("Parse", kParse, "ro"),
+/*25*/ DEFUN("Said", kSaid, "Zr"),
+/*26*/ DEFUN("SetSynonyms", kSetSynonyms, "o"),
+/*27*/ DEFUN("HaveMouse", kHaveMouse, ""),
+/*28*/ DEFUN("SetCursor", kSetCursor, "i*"),
+/*28*/ DEFUN("MoveCursor", kMoveCursor, "ii*"),
+/*29*/ DEFUN("FOpen", kFOpen, "ri"),
+/*2a*/ DEFUN("FPuts", kFPuts, "ir"),
+/*2b*/ DEFUN("FGets", kFGets, "rii"),
+/*2c*/ DEFUN("FClose", kFClose, "i"),
+/*2d*/ DEFUN("SaveGame", kSaveGame, "rirr*"),
+/*2e*/ DEFUN("RestoreGame", kRestoreGame, "rir*"),
+/*2f*/ DEFUN("RestartGame", kRestartGame, ""),
+/*30*/ DEFUN("GameIsRestarting", kGameIsRestarting, "i*"),
+/*31*/ DEFUN("DoSound", kDoSound, "iIo*"),
+/*32*/ DEFUN("NewList", kNewList, ""),
+/*33*/ DEFUN("DisposeList", kDisposeList, "l"),
+/*34*/ DEFUN("NewNode", kNewNode, ".."),
+/*35*/ DEFUN("FirstNode", kFirstNode, "Zl"),
+/*36*/ DEFUN("LastNode", kLastNode, "l"),
+/*37*/ DEFUN("EmptyList", kEmptyList, "l"),
+/*38*/ DEFUN("NextNode", kNextNode, "n!"),
+/*39*/ DEFUN("PrevNode", kPrevNode, "n"),
+/*3a*/ DEFUN("NodeValue", kNodeValue, "Zn!"),
+/*3b*/ DEFUN("AddAfter", kAddAfter, "lnn"),
+/*3c*/ DEFUN("AddToFront", kAddToFront, "ln"),
+/*3d*/ DEFUN("AddToEnd", kAddToEnd, "ln"),
+/*3e*/ DEFUN("FindKey", kFindKey, "l."),
+/*3f*/ DEFUN("DeleteKey", kDeleteKey, "l."),
+/*40*/ DEFUN("Random", kRandom, "i*"),
+/*41*/ DEFUN("Abs", kAbs, "Oi"),
+/*42*/ DEFUN("Sqrt", kSqrt, "i"),
+/*43*/ DEFUN("GetAngle", kGetAngle, "iiii"),
+/*44*/ DEFUN("GetDistance", kGetDistance, "iiiii*"),
+/*45*/ DEFUN("Wait", kWait, "i"),
+/*46*/ DEFUN("GetTime", kGetTime, "i*"),
+/*47*/ DEFUN("StrEnd", kStrEnd, "r"),
+/*48*/ DEFUN("StrCat", kStrCat, "rr"),
+/*49*/ DEFUN("StrCmp", kStrCmp, "rri*"),
+/*4a*/ DEFUN("StrLen", kStrLen, "r"),
+/*4b*/ DEFUN("StrCpy", kStrCpy, "rri*"),
+/*4c*/ DEFUN("Format", kFormat, "r.*"),
+/*4d*/ DEFUN("GetFarText", kGetFarText, "iir"),
+/*4e*/ DEFUN("ReadNumber", kReadNumber, "r"),
+/*4f*/ DEFUN("BaseSetter", kBaseSetter, "o"),
+/*50*/ DEFUN("DirLoop", kDirLoop, "oi"),
+/*51*/ DEFUN("CanBeHere", kCanBeHere, "ol*"),
+/*51*/ DEFUN("CantBeHere", kCanBeHere, "ol*"),
+/*52*/ DEFUN("OnControl", kOnControl, "i*"),
+/*53*/ DEFUN("InitBresen", kInitBresen, "oi*"),
+/*54*/ DEFUN("DoBresen", kDoBresen, "o"),
+/*55*/ DEFUN("DoAvoider", kDoAvoider, "o"),
+/*56*/ DEFUN("SetJump", kSetJump, "oiii"),
+/*57*/ DEFUN("SetDebug", kSetDebug, "i*"),
+/*58*/ NOFUN("InspectObj"),
+/*59*/ NOFUN("ShowSends"),
+/*5a*/ NOFUN("ShowObjs"),
+/*5b*/ NOFUN("ShowFree"),
+/*5c*/ DEFUN("MemoryInfo", kMemoryInfo, "i"),
+/*5d*/ NOFUN("StackUsage"),
+/*5e*/ NOFUN("Profiler"),
+/*5f*/ DEFUN("GetMenu", kGetMenu, "i."),
+/*60*/ DEFUN("SetMenu", kSetMenu, "i.*"),
+/*61*/ DEFUN("GetSaveFiles", kGetSaveFiles, "rrr"),
+/*62*/ DEFUN("GetCWD", kGetCWD, "r"),
+/*63*/ DEFUN("CheckFreeSpace", kCheckFreeSpace, "r"),
+/*64*/ DEFUN("ValidPath", kValidPath, "r"),
+/*65*/ DEFUN("CoordPri", kCoordPri, "i"),
+/*66*/ DEFUN("StrAt", kStrAt, "rii*"),
+#ifdef _WIN32
+/*67*/ DEFUN("DeviceInfo", kDeviceInfo_Win32, "i.*"),
+#else /* !_WIN32 */
+/*67*/ DEFUN("DeviceInfo", kDeviceInfo_Unix, "i.*"),
+#endif
+/*68*/ DEFUN("GetSaveDir", kGetSaveDir, ""),
+/*69*/ DEFUN("CheckSaveGame", kCheckSaveGame, ".*"),
+/*6a*/ DEFUN("ShakeScreen", kShakeScreen, "ii*"),
+/*6b*/ DEFUN("FlushResources", kFlushResources, "i"),
+/*6c*/ DEFUN("TimesSin", kTimesSin, "ii"),
+/*6d*/ DEFUN("TimesCos", kTimesCos, "ii"),
+#if 0
+/*6e*/ NOFUN(NULL),
+/*6f*/ NOFUN(NULL),
+#else
+/*6e*/ DEFUN("6e", kTimesSin, "ii"),
+/*6f*/ DEFUN("6f", kTimesCos, "ii"),
+#endif
+/*70*/ DEFUN("Graph", kGraph, ".*"),
+/*71*/ DEFUN("Joystick", kJoystick, ".*"),
+/*72*/ NOFUN(NULL),
+/*73*/ NOFUN(NULL),
+
+ /* Experimental functions */
+/*74*/ DEFUN("FileIO", kFileIO, "i.*"),
+/*(?)*/ DEFUN("Memory", kMemory, "i.*"),
+/*(?)*/ DEFUN("Sort", kSort, "ooo"),
+/*(?)*/ DEFUN("AvoidPath", kAvoidPath, "ii.*"),
+/*(?)*/ DEFUN("Lock", kLock, "iii*"),
+/*(?)*/ DEFUN("Palette", kPalette, "i*"),
+/*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"),
+
+ /* Non-experimental Functions without a fixed ID */
+
+ DEFUN("CosMult", kTimesCos, "ii"),
+ DEFUN("SinMult", kTimesSin, "ii"),
+/*(?)*/ DEFUN("CosDiv", kCosDiv, "ii"),
+/*(?)*/ DEFUN("PriCoord", kPriCoord, "i"),
+/*(?)*/ DEFUN("SinDiv", kSinDiv, "ii"),
+/*(?)*/ DEFUN("TimesCot", kTimesCot, "ii"),
+/*(?)*/ DEFUN("TimesTan", kTimesTan, "ii"),
+DEFUN("Message", kMessage, ".*"),
+DEFUN("DoAudio", kDoAudio, ".*"),
+
+
+ /* Special and NOP stuff */
+ {KF_NEW, NULL, {k_Unknown, NULL, NULL}},
+
+ {KF_TERMINATOR, NULL, {NULL, NULL, NULL}} /* Terminator */
+};
+
+static const char *argtype_description[] = {"Undetermined (WTF?)", "List","Node","Object","Reference","Arithmetic"};
+
+
+/******************** Kernel Oops ********************/
+
+int
+kernel_oops(state_t *s, const char *file, int line, const char *reason)
+{
+ sciprintf("Kernel Oops in file %s, line %d: %s\n", file, line, reason);
+ fprintf(stderr,"Kernel Oops in file %s, line %d: %s\n", file, line, reason);
+ script_debug_flag = script_error_flag = 1;
+ return 0;
+}
+
+
+/* Allocates a set amount of memory for a specified use and returns a handle to it. */
+reg_t
+kalloc(state_t *s, const char *type, int space)
+{
+ reg_t reg;
+
+ sm_alloc_hunk_entry(&s->seg_manager, type, space, &reg);
+ SCIkdebug(SCIkMEM, "Allocated %d at hunk "PREG" (%s)\n", space, PRINT_REG(reg), type);
+
+ return reg;
+}
+
+int
+has_kernel_function(state_t *s, const char *kname)
+{
+ int i = 0;
+
+ while (s->kernel_names[i])
+ {
+ if (!strcmp(s->kernel_names[i], kname))
+ return 1;
+ i++;
+ }
+
+ return 0;
+}
+
+/* Returns a pointer to the memory indicated by the specified handle */
+byte *
+kmem(state_t *s, reg_t handle)
+{
+ mem_obj_t *mobj = GET_SEGMENT(s->seg_manager, handle.segment, MEM_OBJ_HUNK);
+ hunk_table_t *ht = &(mobj->data.hunks);
+
+ if (!mobj || !ENTRY_IS_VALID(ht, handle.offset)) {
+ SCIkwarn(SCIkERROR, "Error: kmem() with invalid handle\n");
+ return NULL;
+ }
+
+ return (byte *) ht->table[handle.offset].entry.mem;
+}
+
+/* Frees the specified handle. Returns 0 on success, 1 otherwise. */
+int
+kfree(state_t *s, reg_t handle)
+{
+ sm_free_hunk_entry(&s->seg_manager, handle);
+
+ return 0;
+}
+
+
+/*****************************************/
+/************* Kernel functions **********/
+/*****************************************/
+
+char *old_save_dir;
+
+reg_t
+kRestartGame(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1);
+
+ old_save_dir = strdup(deref_save_dir);
+ s->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW;
+ s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED_AT_LEAST_ONCE; /* This appears to help */
+ s->execution_stack_pos = s->execution_stack_base;
+ script_abort_flag = 1; /* Force vm to abort ASAP */
+ return NULL_REG;
+}
+
+
+/* kGameIsRestarting():
+** Returns the restarting_flag in acc
+*/
+reg_t
+kGameIsRestarting(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ char *deref_save_dir = (char*)kernel_dereference_bulk_pointer(s, s->save_dir_copy, 1);
+
+ if (old_save_dir&&deref_save_dir)
+ {
+ strcpy(deref_save_dir, old_save_dir);
+ free(old_save_dir);
+ old_save_dir = NULL;
+ }
+
+ s->r_acc = make_reg(0, (s->restarting_flags & SCI_GAME_WAS_RESTARTED));
+
+ if (argc) {/* Only happens during replay */
+ if (!UKPV(0)) /* Set restarting flag */
+ s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED;
+ }
+
+ return s->r_acc;
+}
+
+reg_t
+kHaveMouse(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+
+ return make_reg (0, (s->have_mouse_flag
+ && gfxop_have_mouse(s->gfx_state))? -1 : 0);
+}
+
+
+
+reg_t
+kMemoryInfo(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ switch (argv[0].offset) {
+ case 0: /* Total free heap memory */
+ case 1: /* Largest heap block available */
+ case 2: /* Largest available hunk memory block */
+ case 3: /* Total amount of hunk memory */
+ case 4: /* Amount of free DOS paragraphs- SCI01 */
+ return make_reg(0, 0x7fff); /* Must not be 0xffff, or some memory calculations will overflow */
+
+ default: SCIkwarn(SCIkWARNING, "Unknown MemoryInfo operation: %04x\n", argv[0].offset);
+ }
+ return NULL_REG;
+}
+
+
+reg_t
+k_Unknown(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ if (funct_nr >= SCI_MAPPED_UNKNOWN_KFUNCTIONS_NR) {
+ SCIkwarn(SCIkSTUB, "Unhandled Unknown function %04x\n", funct_nr);
+ return NULL_REG;
+ } else switch(kfunct_mappers[funct_nr].type) {
+
+ case KF_NEW:
+ return kfunct_mappers[funct_nr].new.fun(s, funct_nr, argc, argv);
+
+ case KF_NONE:
+ default:
+ SCIkwarn(SCIkSTUB, "Unhandled Unknown function %04x\n", funct_nr);
+ return NULL_REG;
+ }
+}
+
+
+reg_t
+kFlushResources(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ run_gc(s);
+ SCIkdebug(SCIkROOM, "Entering room number %d\n", UKPV(0));
+ return s->r_acc;
+}
+
+reg_t
+kSetDebug(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ sciprintf("Debug mode activated\n");
+
+ script_debug_flag = 1; /* Enter debug mode */
+ _debug_seeking = _debug_step_running = 0;
+ return s->r_acc;
+}
+
+#define _K_NEW_GETTIME_TICKS 0
+#define _K_NEW_GETTIME_TIME_12HOUR 1
+#define _K_NEW_GETTIME_TIME_24HOUR 2
+#define _K_NEW_GETTIME_DATE 3
+
+reg_t
+kGetTime(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ struct tm* loc_time;
+ GTimeVal time_prec;
+ time_t the_time;
+ int retval = 0; /* Avoid spurious warning */
+
+#if 0
+ /* Reset optimization flags: If this function is called,
+ ** the game may be waiting for a timeout */
+ s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT
+ | KERNEL_OPT_FLAG_GOT_2NDEVENT);
+#endif
+
+#ifdef _WIN32
+ if (TIMERR_NOERROR != timeBeginPeriod(1))
+ {
+ fprintf(stderr, "timeBeginPeriod(1) failed in kGetTime!\n");
+ }
+#endif /* _WIN32 */
+
+ the_time = time(NULL);
+ loc_time = localtime(&the_time);
+
+#ifdef _WIN32
+ if (TIMERR_NOERROR != timeEndPeriod(1))
+ {
+ fprintf(stderr, "timeEndPeriod(1) failed in kGetTime!\n");
+ }
+#endif /* _WIN32 */
+
+ if (s->version<SCI_VERSION_FTU_NEW_GETTIME) { /* Use old semantics */
+ if (argc) { /* Get seconds since last am/pm switch */
+ retval = loc_time->tm_sec + loc_time->tm_min * 60 + (loc_time->tm_hour % 12) * 3600;
+ SCIkdebug(SCIkTIME, "GetTime(timeofday) returns %d\n", retval);
+ } else { /* Get time since game started */
+ sci_get_current_time (&time_prec);
+ retval = ((time_prec.tv_usec - s->game_start_time.tv_usec) * 60 / 1000000) +
+ (time_prec.tv_sec - s->game_start_time.tv_sec) * 60;
+ SCIkdebug(SCIkTIME, "GetTime(elapsed) returns %d\n", retval);
+ }
+ } else {
+ int mode = UKPV_OR_ALT(0, 0); /* The same strange method is still used for distinguishing
+ mode 0 and the others. We assume that this is safe, though */
+ switch (mode) {
+ case _K_NEW_GETTIME_TICKS : {
+ sci_get_current_time (&time_prec);
+ retval = ((time_prec.tv_usec - s->game_start_time.tv_usec) * 60 / 1000000) +
+ (time_prec.tv_sec - s->game_start_time.tv_sec) * 60;
+ SCIkdebug(SCIkTIME, "GetTime(elapsed) returns %d\n", retval);
+ break;
+ }
+ case _K_NEW_GETTIME_TIME_12HOUR : {
+ loc_time->tm_hour %= 12;
+ retval=(loc_time->tm_min<<6)|(loc_time->tm_hour<<12)|(loc_time->tm_sec);
+ SCIkdebug(SCIkTIME, "GetTime(12h) returns %d\n", retval);
+ break;
+ }
+ case _K_NEW_GETTIME_TIME_24HOUR : {
+ retval=(loc_time->tm_min<<5)|(loc_time->tm_sec>>1)|(loc_time->tm_hour<<11);
+ SCIkdebug(SCIkTIME, "GetTime(24h) returns %d\n", retval);
+ break;
+ }
+ case _K_NEW_GETTIME_DATE : {
+ retval=(loc_time->tm_mon<<5)|loc_time->tm_mday|(loc_time->tm_year<<9);
+ SCIkdebug(SCIkTIME, "GetTime(date) returns %d\n", retval);
+ break;
+ }
+ default: {
+ SCIkdebug(SCIkWARNING, "Attempt to use unknown GetTime mode %d\n", mode);
+ break;
+ }
+ }
+ }
+
+ return make_reg(0, retval);
+}
+
+#define K_MEMORY_ALLOCATE_CRITICAL 1
+#define K_MEMORY_ALLOCATE_NONCRITICAL 2
+#define K_MEMORY_FREE 3
+#define K_MEMORY_MEMCPY 4
+#define K_MEMORY_PEEK 5
+#define K_MEMORY_POKE 6
+
+reg_t
+kMemory(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+
+ switch (UKPV(0)) {
+
+ case K_MEMORY_ALLOCATE_CRITICAL :
+
+ if (!sm_alloc_dynmem(&s->seg_manager, UKPV(1),
+ "kMemory() critical", &s->r_acc)) {
+ SCIkwarn(SCIkERROR, "Critical heap allocation failed\n");
+ script_error_flag = script_debug_flag = 1;
+ }
+
+ return s->r_acc;
+ break;
+
+ case K_MEMORY_ALLOCATE_NONCRITICAL :
+
+ sm_alloc_dynmem(&s->seg_manager, UKPV(1),
+ "kMemory() non-critical", &s->r_acc);
+ break;
+
+ case K_MEMORY_FREE :
+
+ if (sm_free_dynmem(&s->seg_manager, argv[1])) {
+ SCIkwarn(SCIkERROR, "Attempt to kMemory::free() non-dynmem pointer "PREG"!\n",
+ PRINT_REG(argv[1]));
+ }
+ break;
+
+ case K_MEMORY_MEMCPY : {
+ int size = UKPV(3);
+ byte *dest = kernel_dereference_bulk_pointer(s, argv[1], size);
+ byte *src = kernel_dereference_bulk_pointer(s, argv[2], size);
+
+ if (dest && src)
+ memcpy(dest, src, size);
+ else {
+ SCIkdebug(SCIkWARNING, "Warning: Could not execute kMemory:memcpy of %d bytes:\n", size);
+ if (!dest) {
+ SCIkdebug(SCIkWARNING, " dest ptr ("PREG") invalid/memory region too small\n", PRINT_REG(argv[1]));
+ }
+ if (!src) {
+ SCIkdebug(SCIkWARNING, " src ptr ("PREG") invalid/memory region too small\n", PRINT_REG(argv[2]));
+ }
+ }
+
+ break;
+ }
+
+ case K_MEMORY_PEEK : {
+ byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2);
+
+ if (!ref) {
+ SCIkdebug(SCIkERROR, "Attempt to poke invalid memory at "PREG"!\n",
+ PRINT_REG(argv[1]));
+ return s->r_acc;
+ }
+ if (s->seg_manager.heap[argv[1].segment]->type == MEM_OBJ_LOCALS)
+ return *((reg_t *) ref); else
+ return make_reg(0, getInt16(ref));
+ }
+ break;
+
+ case K_MEMORY_POKE : {
+ byte *ref = kernel_dereference_bulk_pointer(s, argv[1], 2);
+
+ if (!ref) {
+ SCIkdebug(SCIkERROR, "Attempt to poke invalid memory at "PREG"!\n",
+ PRINT_REG(argv[1]));
+ return s->r_acc;
+ }
+
+ if (s->seg_manager.heap[argv[1].segment]->type == MEM_OBJ_LOCALS)
+ *((reg_t *) ref) = argv[2]; else
+ {
+ if (argv[2].segment) {
+ SCIkdebug(SCIkERROR, "Attempt to poke memory reference "PREG" to "PREG"!\n",
+ PRINT_REG(argv[2]), PRINT_REG(argv[1]));
+ return s->r_acc;
+ putInt16(ref, argv[2].offset);
+ }
+
+ }
+ return s->r_acc;
+ break;
+
+ }
+ }
+
+ return s->r_acc;
+}
+
+reg_t
+kstub(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ int i;
+
+ SCIkwarn(SCIkWARNING, "Unimplemented syscall: %s[%x](",
+ s->kernel_names[funct_nr], funct_nr);
+
+ for (i = 0; i < argc; i++) {
+ sciprintf(PREG, PRINT_REG(argv[i]));
+ if (i+1 < argc) sciprintf(", ");
+ }
+ sciprintf(")\n");
+ return NULL_REG;
+}
+
+
+reg_t
+kNOP(state_t *s, int funct_nr, int argc, reg_t *argv)
+{
+ char *problem = (char*)(s->kfunct_table[funct_nr].orig_name ?
+ "unmapped" : "NOP");
+
+ SCIkwarn(SCIkWARNING, "Warning: Kernel function 0x%02x invoked: %s", funct_nr, problem);
+
+ if (s->kfunct_table[funct_nr].orig_name &&
+ strcmp(s->kfunct_table[funct_nr].orig_name, SCRIPT_UNKNOWN_FUNCTION_STRING))
+ {
+ sciprintf(" (but its name is known to be %s)", s->kfunct_table[funct_nr].orig_name);
+ }
+
+ sciprintf("\n");
+ return NULL_REG;
+}
+
+
+
+void
+kernel_compile_signature(const char **s)
+{
+ const char *src = *s;
+ char *result;
+ int ellipsis = 0;
+ char v;
+ int index = 0;
+
+ if (!src)
+ return; /* NULL signature: Nothing to do */
+
+ result = (char*)sci_malloc(strlen(*s) + 1);
+
+ while (*src) {
+ char c;
+ v = 0;
+
+ if (ellipsis) {
+ sciprintf("INTERNAL ERROR when compiling kernel"
+ " function signature '%s': non-terminal ellipsis\n", *s,
+ *src);
+ exit(1);
+ }
+
+ do {
+ char cc;
+ cc = c = *src++;
+ if (c >= 'A' || c <= 'Z')
+ cc = c | KSIG_SPEC_SUM_DONE;
+
+ switch (cc) {
+
+ case KSIG_SPEC_LIST:
+ v |= KSIG_LIST;
+ break;
+
+ case KSIG_SPEC_NODE:
+ v |= KSIG_NODE;
+ break;
+
+ case KSIG_SPEC_REF:
+ v |= KSIG_REF;
+ break;
+
+ case KSIG_SPEC_OBJECT:
+ v |= KSIG_OBJECT;
+ break;
+
+ case KSIG_SPEC_ARITHMETIC:
+ v |= KSIG_ARITHMETIC;
+ break;
+
+ case KSIG_SPEC_NULL:
+ v |= KSIG_NULL;
+ break;
+
+ case KSIG_SPEC_ANY:
+ v |= KSIG_ANY;
+ break;
+
+ case KSIG_SPEC_ALLOW_INV:
+ v |= KSIG_ALLOW_INV;
+ break;
+
+ case KSIG_SPEC_ELLIPSIS:
+ v |= KSIG_ELLIPSIS;
+ ellipsis = 1;
+ break;
+
+ default: {
+ sciprintf("INTERNAL ERROR when compiling kernel"
+ " function signature '%s': (%02x) not understood (aka"
+ " '%c')\n",
+ *s, c, c);
+ exit(1);
+ }
+
+ }
+ } while (*src && (*src == KSIG_SPEC_ALLOW_INV ||
+ *src == KSIG_SPEC_ELLIPSIS ||
+ (c < 'a' && c != KSIG_SPEC_ANY)));
+
+ /* To handle sum types */
+ result[index++] = v;
+ }
+
+ result[index] = 0;
+ *s = result; /* Write back */
+}
+
+int
+script_map_kernel(state_t *s)
+{
+ int functnr;
+ int mapped = 0;
+ int ignored = 0;
+ int functions_nr = s->kernel_names_nr;
+ int max_functions_nr
+ = sci_max_allowed_unknown_kernel_functions[s->resmgr
+ ->sci_version];
+
+ if (functions_nr < max_functions_nr) {
+ sciprintf("Warning: SCI version believed to have %d kernel"
+ " functions, but only %d reported-- filling up"
+ " remaining %d\n",
+ max_functions_nr, functions_nr,
+ max_functions_nr - functions_nr);
+
+ functions_nr = max_functions_nr;
+ }
+
+ s->kfunct_table = (kfunct_sig_pair_t*)sci_malloc(sizeof(kfunct_sig_pair_t) * functions_nr);
+
+
+ s->kfunct_nr = functions_nr;
+
+ for (functnr = 0; functnr < functions_nr; functnr++) {
+ int seeker, found = -1;
+ char *sought_name = NULL;
+
+ if (functnr < s->kernel_names_nr)
+ sought_name = s->kernel_names[functnr];
+
+ if (sought_name)
+ for (seeker = 0; (found == -1)
+ && kfunct_mappers[seeker].type != KF_TERMINATOR; seeker++)
+ if (kfunct_mappers[seeker].name
+ && strcmp(kfunct_mappers[seeker].name, sought_name) == 0)
+ found = seeker; /* Found a kernel function with the same name! */
+
+ if (found == -1) {
+ if (sought_name)
+ {
+ sciprintf("Warning: Kernel function %s[%x] unmapped\n",
+ s->kernel_names[functnr], functnr);
+ s->kfunct_table[functnr].fun = kNOP;
+ } else
+ {
+ sciprintf("Warning: Flagging kernel function %x as unknown\n",
+ functnr);
+ s->kfunct_table[functnr].fun = k_Unknown;
+ }
+
+ s->kfunct_table[functnr].signature = NULL;
+ s->kfunct_table[functnr].orig_name = sought_name;
+ } else switch (kfunct_mappers[found].type) {
+
+ case KF_OLD:
+ sciprintf("Emulated kernel function found.\nThis shouldn't happen anymore.");
+ return 1;
+
+ case KF_NONE:
+ s->kfunct_table[functnr].signature = NULL;
+ ++ignored;
+ break;
+
+ case KF_NEW:
+ s->kfunct_table[functnr] = kfunct_mappers[found].new;
+ kernel_compile_signature(&(s->kfunct_table[functnr].signature));
+ ++mapped;
+ break;
+ }
+
+ } /* for all functions requesting to be mapped */
+
+ sciprintf("Handled %d/%d kernel functions, mapping %d",
+ mapped+ignored, s->kernel_names_nr, mapped);
+ if (ignored)
+ sciprintf(" and ignoring %d", ignored);
+ sciprintf(".\n");
+ return 0;
+}
+
+void
+free_kfunct_tables(state_t *s)
+{
+ sci_free(s->kfunct_table);
+ s->kfunct_table = NULL;
+
+}
+int
+determine_reg_type(state_t *s, reg_t reg, int allow_invalid)
+{
+ mem_obj_t *mobj;
+
+ if (!reg.segment) {
+ if (!reg.offset)
+ return KSIG_ARITHMETIC | KSIG_NULL;
+ return KSIG_ARITHMETIC;
+ }
+
+ if ((reg.segment >= s->seg_manager.heap_size)
+ || !s->seg_manager.heap[reg.segment])
+ return 0; /* Invalid */
+
+ mobj = s->seg_manager.heap[reg.segment];
+
+ switch (mobj->type) {
+
+ case MEM_OBJ_SCRIPT:
+ if (reg.offset <= mobj->data.script.buf_size
+ && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
+ && RAW_IS_OBJECT(mobj->data.script.buf + reg.offset)) {
+ int idx = RAW_GET_CLASS_INDEX(&(mobj->data.script), reg);
+ if (idx >= 0 && idx < mobj->data.script.objects_nr)
+ return KSIG_OBJECT;
+ else
+ return KSIG_REF;
+ } else
+ return KSIG_REF;
+
+ case MEM_OBJ_CLONES:
+ if (allow_invalid || ENTRY_IS_VALID(&(mobj->data.clones), reg.offset))
+ return KSIG_OBJECT;
+ else
+ return KSIG_OBJECT | KSIG_INVALID;
+
+ case MEM_OBJ_LOCALS:
+ if (allow_invalid || reg.offset < mobj->data.locals.nr * sizeof(reg_t))
+ return KSIG_REF;
+ else
+ return KSIG_REF | KSIG_INVALID;
+
+ case MEM_OBJ_STACK:
+ if (allow_invalid || reg.offset < mobj->data.stack.nr * sizeof(reg_t))
+ return KSIG_REF;
+ else
+ return KSIG_REF | KSIG_INVALID;
+
+ case MEM_OBJ_SYS_STRINGS:
+ if (allow_invalid || (reg.offset < SYS_STRINGS_MAX
+ && mobj->data.sys_strings.strings[reg.offset].name))
+ return KSIG_REF;
+ else
+ return KSIG_REF | KSIG_INVALID;
+
+ case MEM_OBJ_LISTS:
+ if (allow_invalid || ENTRY_IS_VALID(&(mobj->data.lists), reg.offset))
+ return KSIG_LIST;
+ else
+ return KSIG_LIST | KSIG_INVALID;
+
+ case MEM_OBJ_NODES:
+ if (allow_invalid || ENTRY_IS_VALID(&(mobj->data.nodes), reg.offset))
+ return KSIG_NODE;
+ else
+ return KSIG_NODE | KSIG_INVALID;
+
+ case MEM_OBJ_DYNMEM:
+ if (allow_invalid || reg.offset < mobj->data.dynmem.size)
+ return KSIG_REF;
+ else
+ return KSIG_REF | KSIG_INVALID;
+
+ default:
+ return 0;
+
+ }
+}
+
+const char *
+kernel_argtype_description(int type)
+{
+ type &= ~KSIG_INVALID;
+
+ return argtype_description[sci_ffs(type)];
+}
+
+int
+kernel_matches_signature(state_t *s, const char *sig, int argc, reg_t *argv)
+{
+ if (!sig)
+ return 1;
+
+ while (*sig && argc) {
+ if ((*sig & KSIG_ANY) != KSIG_ANY) {
+ int type = determine_reg_type(s, *argv, *sig & KSIG_ALLOW_INV);
+
+ if (!type) {
+ sciprintf("[KERN] Could not determine type of ref "PREG";"
+ " failing signature check\n",
+ PRINT_REG(*argv));
+ return 0;
+ }
+
+ if (type & KSIG_INVALID) {
+ sciprintf("[KERN] ref "PREG" was determined to be a %s, "
+ "but the reference itself is invalid\n",
+ PRINT_REG(*argv), kernel_argtype_description(type));
+ return 0;
+ }
+
+ if (!(type & *sig))
+ return 0;
+
+ }
+ if (!(*sig & KSIG_ELLIPSIS))
+ ++sig;
+ ++argv;
+ --argc;
+ }
+
+ if (argc)
+ return 0; /* Too many arguments */
+ else
+ return (*sig == 0 || (*sig & KSIG_ELLIPSIS));
+}
+
+static inline void *
+_kernel_dereference_pointer(struct _state *s, reg_t pointer, int entries, int align)
+{
+ int maxsize;
+ void *retval = sm_dereference(&s->seg_manager, pointer, &maxsize);
+
+ if (pointer.offset & (align-1)) {
+ SCIkdebug(SCIkERROR, "Unaligned pointer read: "PREG" expected with %d alignment!\n",
+ PRINT_REG(pointer), align);
+ return NULL;
+ }
+
+ if (entries > maxsize) {
+ SCIkdebug(SCIkERROR, "Trying to dereference pointer "PREG" beyond end of segment!\n",
+ PRINT_REG(pointer));
+ return NULL;
+ }
+ return retval;
+
+}
+
+byte *
+kernel_dereference_bulk_pointer(struct _state *s, reg_t pointer, int entries)
+{
+ return (byte*)_kernel_dereference_pointer(s, pointer, entries, 1);
+}
+
+
+reg_t *
+kernel_dereference_reg_pointer(struct _state *s, reg_t pointer, int entries)
+{
+ return (reg_t*)_kernel_dereference_pointer(s, pointer, entries, sizeof(reg_t));
+}