aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/engine/kscripts.cpp76
-rw-r--r--engines/sci/engine/selector.cpp211
-rw-r--r--engines/sci/engine/vm.cpp104
-rw-r--r--engines/sci/module.mk1
4 files changed, 212 insertions, 180 deletions
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index ce7656f47e..2978a2a2e2 100644
--- a/engines/sci/engine/kscripts.cpp
+++ b/engines/sci/engine/kscripts.cpp
@@ -31,82 +31,6 @@
namespace Sci {
-reg_t read_selector(SegManager *segMan, reg_t object, Selector selector_id, const char *file, int line) {
- ObjVarRef address;
-
- if (lookup_selector(segMan, object, selector_id, &address, NULL) != kSelectorVariable)
- return NULL_REG;
- else
- return *address.getPointer(segMan);
-}
-
-void write_selector(SegManager *segMan, reg_t object, Selector selector_id, reg_t value, const char *fname, int line) {
- ObjVarRef address;
-
- if ((selector_id < 0) || (selector_id > (int)((SciEngine*)g_engine)->getKernel()->getSelectorNamesSize())) {
- warning("Attempt to write to invalid selector %d of"
- " object at %04x:%04x (%s L%d).", selector_id, PRINT_REG(object), fname, line);
- return;
- }
-
- if (lookup_selector(segMan, object, selector_id, &address, NULL) != kSelectorVariable)
- warning("Selector '%s' of object at %04x:%04x could not be"
- " written to (%s L%d)", ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line);
- else
- *address.getPointer(segMan) = value;
-}
-
-int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvocation noinvalid, int kfunct,
- StackPtr k_argp, int k_argc, const char *fname, int line, int argc, ...) {
- va_list argp;
- int i;
- int framesize = 2 + 1 * argc;
- reg_t address;
- int slc_type;
- StackPtr stackframe = k_argp + k_argc;
-
- stackframe[0] = make_reg(0, selector_id); // The selector we want to call
- stackframe[1] = make_reg(0, argc); // Argument count
-
- slc_type = lookup_selector(s->segMan, object, selector_id, NULL, &address);
-
- if (slc_type == kSelectorNone) {
- warning("Selector '%s' of object at %04x:%04x could not be invoked (%s L%d)",
- ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line);
- if (noinvalid == kStopOnInvalidSelector)
- error("[Kernel] Not recoverable: VM was halted");
- return 1;
- }
- if (slc_type == kSelectorVariable) // Swallow silently
- return 0;
-
- va_start(argp, argc);
- for (i = 0; i < argc; i++) {
- reg_t arg = va_arg(argp, reg_t);
- stackframe[2 + i] = arg; // Write each argument
- }
- va_end(argp);
-
- // Write "kernel" call to the stack, for debugging:
- ExecStack *xstack;
- xstack = add_exec_stack_entry(s, NULL_REG, NULL, NULL_REG, k_argc, k_argp - 1, 0, NULL_REG,
- s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
- xstack->selector = -42 - kfunct; // Evil debugging hack to identify kernel function
- xstack->type = EXEC_STACK_TYPE_KERNEL;
-
- // Now commit the actual function:
- xstack = send_selector(s, object, object, stackframe, framesize, stackframe);
-
- xstack->sp += argc + 2;
- xstack->fp += argc + 2;
-
- run_vm(s, 0); // Start a new vm
-
- s->_executionStack.pop_back(); // Get rid of the extra stack entry
-
- return 0;
-}
-
// Loads arbitrary resources of type 'restype' with resource numbers 'resnrs'
// This implementation ignores all resource numbers except the first one.
reg_t kLoad(EngineState *s, int, int argc, reg_t *argv) {
diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp
new file mode 100644
index 0000000000..2886bd0c77
--- /dev/null
+++ b/engines/sci/engine/selector.cpp
@@ -0,0 +1,211 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "sci/sci.h"
+#include "sci/engine/state.h"
+
+namespace Sci {
+
+reg_t read_selector(SegManager *segMan, reg_t object, Selector selector_id, const char *file, int line) {
+ ObjVarRef address;
+
+ if (lookup_selector(segMan, object, selector_id, &address, NULL) != kSelectorVariable)
+ return NULL_REG;
+ else
+ return *address.getPointer(segMan);
+}
+
+void write_selector(SegManager *segMan, reg_t object, Selector selector_id, reg_t value, const char *fname, int line) {
+ ObjVarRef address;
+
+ if ((selector_id < 0) || (selector_id > (int)((SciEngine*)g_engine)->getKernel()->getSelectorNamesSize())) {
+ warning("Attempt to write to invalid selector %d of"
+ " object at %04x:%04x (%s L%d).", selector_id, PRINT_REG(object), fname, line);
+ return;
+ }
+
+ if (lookup_selector(segMan, object, selector_id, &address, NULL) != kSelectorVariable)
+ warning("Selector '%s' of object at %04x:%04x could not be"
+ " written to (%s L%d)", ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line);
+ else
+ *address.getPointer(segMan) = value;
+}
+
+int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvocation noinvalid, int kfunct,
+ StackPtr k_argp, int k_argc, const char *fname, int line, int argc, ...) {
+ va_list argp;
+ int i;
+ int framesize = 2 + 1 * argc;
+ reg_t address;
+ int slc_type;
+ StackPtr stackframe = k_argp + k_argc;
+
+ stackframe[0] = make_reg(0, selector_id); // The selector we want to call
+ stackframe[1] = make_reg(0, argc); // Argument count
+
+ slc_type = lookup_selector(s->segMan, object, selector_id, NULL, &address);
+
+ if (slc_type == kSelectorNone) {
+ warning("Selector '%s' of object at %04x:%04x could not be invoked (%s L%d)",
+ ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line);
+ if (noinvalid == kStopOnInvalidSelector)
+ error("[Kernel] Not recoverable: VM was halted");
+ return 1;
+ }
+ if (slc_type == kSelectorVariable) // Swallow silently
+ return 0;
+
+ va_start(argp, argc);
+ for (i = 0; i < argc; i++) {
+ reg_t arg = va_arg(argp, reg_t);
+ stackframe[2 + i] = arg; // Write each argument
+ }
+ va_end(argp);
+
+ // Write "kernel" call to the stack, for debugging:
+ ExecStack *xstack;
+ xstack = add_exec_stack_entry(s, NULL_REG, NULL, NULL_REG, k_argc, k_argp - 1, 0, NULL_REG,
+ s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS);
+ xstack->selector = -42 - kfunct; // Evil debugging hack to identify kernel function
+ xstack->type = EXEC_STACK_TYPE_KERNEL;
+
+ // Now commit the actual function:
+ xstack = send_selector(s, object, object, stackframe, framesize, stackframe);
+
+ xstack->sp += argc + 2;
+ xstack->fp += argc + 2;
+
+ run_vm(s, 0); // Start a new vm
+
+ s->_executionStack.pop_back(); // Get rid of the extra stack entry
+
+ return 0;
+}
+
+static int _obj_locate_varselector(SegManager *segMan, Object *obj, Selector slc) {
+ // Determines if obj explicitly defines slc as a varselector
+ // Returns -1 if not found
+ byte *buf;
+ uint varnum;
+
+ if (getSciVersion() < SCI_VERSION_1_1) {
+ varnum = obj->variable_names_nr;
+ int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET;
+ buf = obj->base_obj + selector_name_offset;
+ } else {
+ if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS))
+ obj = segMan->getObject(obj->getSuperClassSelector());
+
+ buf = (byte *)obj->base_vars;
+ varnum = obj->_variables[1].toUint16();
+ }
+
+ for (uint i = 0; i < varnum; i++)
+ if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it?
+ return i; // report success
+
+ return -1; // Failed
+}
+
+static int _class_locate_funcselector(Object *obj, Selector slc) {
+ // Determines if obj is a class and explicitly defines slc as a funcselector
+ // Does NOT say anything about obj's superclasses, i.e. failure may be
+ // returned even if one of the superclasses defines the funcselector.
+ int funcnum = obj->methods_nr;
+ int i;
+
+ for (i = 0; i < funcnum; i++)
+ if (obj->getFuncSelector(i) == slc) // Found it?
+ return i; // report success
+
+ return -1; // Failed
+}
+
+static SelectorType _lookup_selector_function(SegManager *segMan, int seg_id, Object *obj, Selector selector_id, reg_t *fptr) {
+ int index;
+
+ // "recursive" lookup
+
+ while (obj) {
+ index = _class_locate_funcselector(obj, selector_id);
+
+ if (index >= 0) {
+ if (fptr) {
+ *fptr = obj->getFunction(index);
+ }
+
+ return kSelectorMethod;
+ } else {
+ seg_id = obj->getSuperClassSelector().segment;
+ obj = segMan->getObject(obj->getSuperClassSelector());
+ }
+ }
+
+ return kSelectorNone;
+}
+
+SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) {
+ Object *obj = segMan->getObject(obj_location);
+ Object *species;
+ int index;
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+
+ // Early SCI versions used the LSB in the selector ID as a read/write
+ // toggle, meaning that we must remove it for selector lookup.
+ if (oldScriptHeader)
+ selector_id &= ~1;
+
+ if (!obj) {
+ error("lookup_selector(): Attempt to send to non-object or invalid script. Address was %04x:%04x",
+ PRINT_REG(obj_location));
+ }
+
+ if (obj->isClass())
+ species = obj;
+ else
+ species = segMan->getObject(obj->getSpeciesSelector());
+
+
+ if (!obj) {
+ error("lookup_selector(): Error while looking up Species class.\nOriginal address was %04x:%04x. Species address was %04x:%04x",
+ PRINT_REG(obj_location), PRINT_REG(obj->getSpeciesSelector()));
+ return kSelectorNone;
+ }
+
+ index = _obj_locate_varselector(segMan, obj, selector_id);
+
+ if (index >= 0) {
+ // Found it as a variable
+ if (varp) {
+ varp->obj = obj_location;
+ varp->varindex = index;
+ }
+ return kSelectorVariable;
+ }
+
+ return _lookup_selector_function(segMan, obj_location.segment, obj, selector_id, fptr);
+}
+
+} // End of namespace Sci
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index b114af1034..be09cd5de0 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -1393,110 +1393,6 @@ void run_vm(EngineState *s, int restoring) {
}
}
-static int _obj_locate_varselector(SegManager *segMan, Object *obj, Selector slc) {
- // Determines if obj explicitly defines slc as a varselector
- // Returns -1 if not found
- byte *buf;
- uint varnum;
-
- if (getSciVersion() < SCI_VERSION_1_1) {
- varnum = obj->variable_names_nr;
- int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET;
- buf = obj->base_obj + selector_name_offset;
- } else {
- if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS))
- obj = segMan->getObject(obj->getSuperClassSelector());
-
- buf = (byte *)obj->base_vars;
- varnum = obj->_variables[1].toUint16();
- }
-
- for (uint i = 0; i < varnum; i++)
- if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it?
- return i; // report success
-
- return -1; // Failed
-}
-
-static int _class_locate_funcselector(Object *obj, Selector slc) {
- // Determines if obj is a class and explicitly defines slc as a funcselector
- // Does NOT say anything about obj's superclasses, i.e. failure may be
- // returned even if one of the superclasses defines the funcselector.
- int funcnum = obj->methods_nr;
- int i;
-
- for (i = 0; i < funcnum; i++)
- if (obj->getFuncSelector(i) == slc) // Found it?
- return i; // report success
-
- return -1; // Failed
-}
-
-static SelectorType _lookup_selector_function(SegManager *segMan, int seg_id, Object *obj, Selector selector_id, reg_t *fptr) {
- int index;
-
- // "recursive" lookup
-
- while (obj) {
- index = _class_locate_funcselector(obj, selector_id);
-
- if (index >= 0) {
- if (fptr) {
- *fptr = obj->getFunction(index);
- }
-
- return kSelectorMethod;
- } else {
- seg_id = obj->getSuperClassSelector().segment;
- obj = segMan->getObject(obj->getSuperClassSelector());
- }
- }
-
- return kSelectorNone;
-}
-
-SelectorType lookup_selector(SegManager *segMan, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) {
- Object *obj = segMan->getObject(obj_location);
- Object *species;
- int index;
- bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
-
- // Early SCI versions used the LSB in the selector ID as a read/write
- // toggle, meaning that we must remove it for selector lookup.
- if (oldScriptHeader)
- selector_id &= ~1;
-
- if (!obj) {
- error("lookup_selector(): Attempt to send to non-object or invalid script. Address was %04x:%04x",
- PRINT_REG(obj_location));
- }
-
- if (obj->isClass())
- species = obj;
- else
- species = segMan->getObject(obj->getSpeciesSelector());
-
-
- if (!obj) {
- error("lookup_selector(): Error while looking up Species class.\nOriginal address was %04x:%04x. Species address was %04x:%04x",
- PRINT_REG(obj_location), PRINT_REG(obj->getSpeciesSelector()));
- return kSelectorNone;
- }
-
- index = _obj_locate_varselector(segMan, obj, selector_id);
-
- if (index >= 0) {
- // Found it as a variable
- if (varp) {
- varp->obj = obj_location;
- varp->varindex = index;
- }
- return kSelectorVariable;
- }
-
- return _lookup_selector_function(segMan, obj_location.segment, obj, selector_id, fptr);
-}
-
#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segMan->getClassAddress(id, SCRIPT_GET_LOCK, reg))
int script_instantiate_common(ResourceManager *resMan, SegManager *segMan, int script_nr, Resource **script, Resource **heap, int *was_new) {
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index d8775e0e57..1c1a930e31 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -30,6 +30,7 @@ MODULE_OBJS = \
engine/savegame.o \
engine/script.o \
engine/scriptdebug.o \
+ engine/selector.o \
engine/seg_manager.o \
engine/segment.o \
engine/static_selectors.o \