diff options
Diffstat (limited to 'engines/sci/engine')
| -rw-r--r-- | engines/sci/engine/kscripts.cpp | 76 | ||||
| -rw-r--r-- | engines/sci/engine/selector.cpp | 211 | ||||
| -rw-r--r-- | engines/sci/engine/vm.cpp | 104 | 
3 files changed, 211 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) { | 
