diff options
Diffstat (limited to 'engines/sci/engine/vm.cpp')
| -rw-r--r-- | engines/sci/engine/vm.cpp | 141 | 
1 files changed, 78 insertions, 63 deletions
| diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index fbdb3d1c85..67b15cd212 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -204,15 +204,15 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i  #define GET_OP_SIGNED_FLEX() ((opcode & 1)? GET_OP_SIGNED_BYTE() : GET_OP_SIGNED_WORD())  ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) { -	int seg = s->seg_manager->segGet(script); -	Script *scr = s->seg_manager->getScriptIfLoaded(seg); +	int seg = s->segmentManager->segGet(script); +	Script *scr = s->segmentManager->getScriptIfLoaded(seg);  	if (!scr)  // Script not present yet? -		seg = script_instantiate(s->resmgr, s->seg_manager, s->_version, script); +		seg = script_instantiate(s->resourceManager, s->segmentManager, script);  	else  		scr->unmarkDeleted(); -	int temp = s->seg_manager->validateExportFunc(pubfunct, seg); +	int temp = s->segmentManager->validateExportFunc(pubfunct, seg);  	if (!temp) {  		error("Request for invalid exported function 0x%x of script 0x%x", pubfunct, script);  		return NULL; @@ -285,7 +285,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  			Breakpoint *bp;  			char method_name [256]; -			sprintf(method_name, "%s::%s", obj_get_name(s->seg_manager, s->_version, send_obj), ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector).c_str()); +			sprintf(method_name, "%s::%s", obj_get_name(s->segmentManager, send_obj), ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector).c_str());  			bp = s->bp_list;  			while (bp) { @@ -310,7 +310,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt  #endif // VM_DEBUG_SEND  		ObjVarRef varp; -		switch (lookup_selector(s, send_obj, selector, &varp, &funcp)) { +		switch (lookup_selector(s->segmentManager, send_obj, selector, &varp, &funcp)) {  		case kSelectorNone:  			error("Send to invalid selector 0x%x of object at %04x:%04x", 0xffff & selector, PRINT_REG(send_obj)); @@ -467,7 +467,7 @@ void vm_handle_fatal_error(EngineState *s, int line, const char *file) {  }  static reg_t pointer_add(EngineState *s, reg_t base, int offset) { -	MemObject *mobj = GET_SEGMENT_ANY(*s->seg_manager, base.segment); +	MemObject *mobj = GET_SEGMENT_ANY(*s->segmentManager, base.segment);  	if (!mobj) {  		error("[VM] Error: Attempt to add %d to invalid pointer %04x:%04x", offset, PRINT_REG(base)); @@ -520,8 +520,8 @@ void run_vm(EngineState *s, int restoring) {  	// Current execution data:  	scriptState.xs = &(s->_executionStack.back());  	ExecStack *xs_new = NULL; -	Object *obj = obj_get(s->seg_manager, s->_version, scriptState.xs->objp); -	Script *local_script = s->seg_manager->getScriptIfLoaded(scriptState.xs->local_segment); +	Object *obj = obj_get(s->segmentManager, scriptState.xs->objp); +	Script *local_script = s->segmentManager->getScriptIfLoaded(scriptState.xs->local_segment);  	int old_execution_stack_base = s->execution_stack_base;  	// Used to detect the stack bottom, for "physical" returns  	const byte *code_buf = NULL; // (Avoid spurious warning) @@ -567,7 +567,7 @@ void run_vm(EngineState *s, int restoring) {  			scriptState.xs = &(s->_executionStack.back());  			s->_executionStackPosChanged = false; -			scr = s->seg_manager->getScriptIfLoaded(scriptState.xs->addr.pc.segment); +			scr = s->segmentManager->getScriptIfLoaded(scriptState.xs->addr.pc.segment);  			if (!scr) {  				// No script? Implicit return via fake instruction buffer  				warning("Running on non-existant script in segment %x", scriptState.xs->addr.pc.segment); @@ -580,12 +580,12 @@ void run_vm(EngineState *s, int restoring) {  				scr = NULL;  				obj = NULL;  			} else { -				obj = obj_get(s->seg_manager, s->_version, scriptState.xs->objp); +				obj = obj_get(s->segmentManager, scriptState.xs->objp);  				code_buf = scr->buf;  #ifndef DISABLE_VALIDATIONS  				code_buf_size = scr->buf_size;  #endif -				local_script = s->seg_manager->getScriptIfLoaded(scriptState.xs->local_segment); +				local_script = s->segmentManager->getScriptIfLoaded(scriptState.xs->local_segment);  				if (!local_script) {  					warning("Could not find local script from segment %x", scriptState.xs->local_segment);  					local_script = NULL; @@ -917,17 +917,22 @@ void run_vm(EngineState *s, int restoring) {  			gc_countdown(s);  			scriptState.xs->sp -= (opparams[1] >> 1) + 1; -			if (!((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) { -				scriptState.xs->sp -= scriptState.restAdjust; -				s->restAdjust = 0; // We just used up the scriptState.restAdjust, remember? + +			{ +				bool oldScriptHeader = (s->segmentManager->sciVersion() == SCI_VERSION_0_EARLY); +				if (!oldScriptHeader) { +					scriptState.xs->sp -= scriptState.restAdjust; +					s->restAdjust = 0; // We just used up the scriptState.restAdjust, remember? +				}  			}  			if (opparams[0] >= (int)((SciEngine*)g_engine)->getKernel()->_kernelFuncs.size()) {  				error("Invalid kernel function 0x%x requested", opparams[0]);  			} else {  				int argc = ASSERT_ARITHMETIC(scriptState.xs->sp[0]); +				bool oldScriptHeader = (s->segmentManager->sciVersion() == SCI_VERSION_0_EARLY); -				if (!((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) +				if (!oldScriptHeader)  					argc += scriptState.restAdjust;  				if (((SciEngine*)g_engine)->getKernel()->_kernelFuncs[opparams[0]].signature @@ -947,8 +952,11 @@ void run_vm(EngineState *s, int restoring) {  				xs_new = &(s->_executionStack.back());  				s->_executionStackPosChanged = true; -				if (!((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) -					scriptState.restAdjust = s->restAdjust; +				{ +					bool oldScriptHeader = (s->segmentManager->sciVersion() == SCI_VERSION_0_EARLY); +					if (!oldScriptHeader) +						scriptState.restAdjust = s->restAdjust; +				}  			}  			break; @@ -1038,7 +1046,7 @@ void run_vm(EngineState *s, int restoring) {  			break;  		case 0x28: // class -			s->r_acc = s->seg_manager->get_class_address((unsigned)opparams[0], SCRIPT_GET_LOCK, +			s->r_acc = s->segmentManager->get_class_address((unsigned)opparams[0], SCRIPT_GET_LOCK,  											scriptState.xs->addr.pc);  			break; @@ -1058,7 +1066,7 @@ void run_vm(EngineState *s, int restoring) {  			break;  		case 0x2b: // super -			r_temp = s->seg_manager->get_class_address(opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc); +			r_temp = s->segmentManager->get_class_address(opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc);  			if (!r_temp.segment)  				error("[VM]: Invalid superclass in object"); @@ -1156,7 +1164,7 @@ void run_vm(EngineState *s, int restoring) {  		case 0x39: // lofsa  			s->r_acc.segment = scriptState.xs->addr.pc.segment; -			if (s->_version >= SCI_VERSION_1_1) { +			if (s->resourceManager->sciVersion() >= SCI_VERSION_1_1) {  				s->r_acc.offset = opparams[0] + local_script->script_size;  			} else {  				if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute()) @@ -1176,7 +1184,7 @@ void run_vm(EngineState *s, int restoring) {  		case 0x3a: // lofss  			r_temp.segment = scriptState.xs->addr.pc.segment; -			if (s->_version >= SCI_VERSION_1_1) { +			if (s->resourceManager->sciVersion() >= SCI_VERSION_1_1) {  				r_temp.offset = opparams[0] + local_script->script_size;  			} else {  				if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute()) @@ -1390,12 +1398,12 @@ void run_vm(EngineState *s, int restoring) {  	}  } -static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) { +static int _obj_locate_varselector(SegManager *segManager, Object *obj, Selector slc) {  	// Determines if obj explicitly defines slc as a varselector  	// Returns -1 if not found -	SciVersion version = s->_version;	// for the selector defines +	SciVersion version = segManager->sciVersion();	// for the selector defines -	if (s->_version < SCI_VERSION_1_1) { +	if (version < SCI_VERSION_1_1) {  		int varnum = obj->variable_names_nr;  		int selector_name_offset = varnum * 2 + SCRIPT_SELECTOR_OFFSET;  		int i; @@ -1414,7 +1422,7 @@ static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) {  		int varnum = obj->_variables[1].offset;  		if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) -			buf = ((byte *) obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR])->base_vars); +			buf = ((byte *) obj_get(segManager, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR])->base_vars);  		for (i = 0; i < varnum; i++)  			if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it? @@ -1424,7 +1432,7 @@ static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) {  	}  } -static int _class_locate_funcselector(EngineState *s, Object *obj, Selector slc) { +static int _class_locate_funcselector(Object *obj, Selector slc, SciVersion version) {  	// 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. @@ -1438,14 +1446,14 @@ static int _class_locate_funcselector(EngineState *s, Object *obj, Selector slc)  	return -1; // Failed  } -static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object *obj, Selector selector_id, reg_t *fptr) { +static SelectorType _lookup_selector_function(SegManager *segManager, int seg_id, Object *obj, Selector selector_id, reg_t *fptr) {  	int index; -	SciVersion version = s->_version;	// for the selector defines +	SciVersion version = segManager->sciVersion();	// for the selector defines  	// "recursive" lookup  	while (obj) { -		index = _class_locate_funcselector(s, obj, selector_id); +		index = _class_locate_funcselector(obj, selector_id, version);  		if (index >= 0) {  			if (fptr) { @@ -1455,22 +1463,23 @@ static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object  			return kSelectorMethod;  		} else {  			seg_id = obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].segment; -			obj = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); +			obj = obj_get(segManager, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);  		}  	}  	return kSelectorNone;  } -SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) { -	Object *obj = obj_get(s->seg_manager, s->_version, obj_location); +SelectorType lookup_selector(SegManager *segManager, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) { +	Object *obj = obj_get(segManager, obj_location);  	Object *species;  	int index; -	SciVersion version = s->_version;	// for the selector defines +	SciVersion version = segManager->sciVersion();	// for the selector defines +	bool oldScriptHeader = (version == 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 (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) +	if (oldScriptHeader)  		selector_id &= ~1;  	if (!obj) { @@ -1481,7 +1490,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select  	if (IS_CLASS(obj))  		species = obj;  	else -		species = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SPECIES_SELECTOR]); +		species = obj_get(segManager, obj->_variables[SCRIPT_SPECIES_SELECTOR]);  	if (!obj) { @@ -1490,7 +1499,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select  		return kSelectorNone;  	} -	index = _obj_locate_varselector(s, obj, selector_id); +	index = _obj_locate_varselector(segManager, obj, selector_id);  	if (index >= 0) {  		// Found it as a variable @@ -1501,7 +1510,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select  		return kSelectorVariable;  	} -	return _lookup_selector_function(s, obj_location.segment, obj, selector_id, fptr); +	return _lookup_selector_function(segManager, obj_location.segment, obj, selector_id, fptr);  }  reg_t script_lookup_export(SegManager *segManager, int script_nr, int export_index) { @@ -1512,19 +1521,19 @@ reg_t script_lookup_export(SegManager *segManager, int script_nr, int export_ind  #define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segManager->get_class_address(id, SCRIPT_GET_LOCK, reg)) -int script_instantiate_common(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr, Resource **script, Resource **heap, int *was_new) { +int script_instantiate_common(ResourceManager *resourceManager, SegManager *segManager, int script_nr, Resource **script, Resource **heap, int *was_new) {  	int seg_id;  	reg_t reg;  	*was_new = 1; -	*script = resMgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0); -	if (version >= SCI_VERSION_1_1) -		*heap = resMgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); +	*script = resourceManager->findResource(ResourceId(kResourceTypeScript, script_nr), 0); +	if (resourceManager->sciVersion() >= SCI_VERSION_1_1) +		*heap = resourceManager->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); -	if (!*script || (version >= SCI_VERSION_1_1 && !heap)) { +	if (!*script || (resourceManager->sciVersion() >= SCI_VERSION_1_1 && !heap)) {  		warning("Script 0x%x requested but not found", script_nr); -		if (version >= SCI_VERSION_1_1) { +		if (resourceManager->sciVersion() >= SCI_VERSION_1_1) {  			if (*heap)  				warning("Inconsistency: heap resource WAS found");  			else if (*script) @@ -1566,7 +1575,7 @@ int script_instantiate_common(ResourceManager *resMgr, SegManager *segManager, S  	return seg_id;  } -int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, SciVersion version, bool oldScriptHeader, int script_nr) { +int script_instantiate_sci0(ResourceManager *resourceManager, SegManager *segManager, int script_nr) {  	int objtype;  	unsigned int objlength;  	reg_t reg; @@ -1575,8 +1584,10 @@ int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, Sci  	int magic_pos_adder; // Usually 0; 2 for older SCI versions  	Resource *script;  	int was_new; +	SciVersion version = resourceManager->sciVersion(); +	bool oldScriptHeader = (version == SCI_VERSION_0_EARLY); -	seg_id = script_instantiate_common(resMgr, segManager, version, script_nr, &script, NULL, &was_new); +	seg_id = script_instantiate_common(resourceManager, segManager, script_nr, &script, NULL, &was_new);  	if (was_new)  		return seg_id; @@ -1690,7 +1701,7 @@ int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, Sci  			// Instantiate the superclass, if neccessary  			obj->_variables[SCRIPT_SPECIES_SELECTOR] = INST_LOOKUP_CLASS(obj->_variables[SCRIPT_SPECIES_SELECTOR].offset); -			base_obj = obj_get(segManager, version, obj->_variables[SCRIPT_SPECIES_SELECTOR]); +			base_obj = obj_get(segManager, obj->_variables[SCRIPT_SPECIES_SELECTOR]);  			obj->variable_names_nr = base_obj->_variables.size();  			obj->base_obj = base_obj->base_obj;  			// Copy base from species class, as we need its selector IDs @@ -1716,14 +1727,14 @@ int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, Sci  	return reg.segment;		// instantiation successful  } -int script_instantiate_sci11(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) { +int script_instantiate_sci11(ResourceManager *resourceManager, SegManager *segManager, int script_nr) {  	Resource *script, *heap;  	int seg_id;  	int heap_start;  	reg_t reg;  	int was_new; -	seg_id = script_instantiate_common(resMgr, segManager, version, script_nr, &script, &heap, &was_new); +	seg_id = script_instantiate_common(resourceManager, segManager, script_nr, &script, &heap, &was_new);  	if (was_new)  		return seg_id; @@ -1753,17 +1764,19 @@ int script_instantiate_sci11(ResourceManager *resMgr, SegManager *segManager, Sc  	return seg_id;  } -int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) { -	if (version >= SCI_VERSION_1_1) -		return script_instantiate_sci11(resMgr, segManager, version, script_nr); +int script_instantiate(ResourceManager *resourceManager, SegManager *segManager, int script_nr) { +	if (resourceManager->sciVersion() >= SCI_VERSION_1_1) +		return script_instantiate_sci11(resourceManager, segManager, script_nr);  	else -		return script_instantiate_sci0(resMgr, segManager, version, (version == SCI_VERSION_0_EARLY), script_nr); +		return script_instantiate_sci0(resourceManager, segManager, script_nr);  } -void script_uninstantiate_sci0(SegManager *segManager, SciVersion version, int script_nr, SegmentId seg) { -	reg_t reg = make_reg(seg, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader() ? 2 : 0); +void script_uninstantiate_sci0(SegManager *segManager, int script_nr, SegmentId seg) { +	bool oldScriptHeader = (segManager->sciVersion() == SCI_VERSION_0_EARLY); +	reg_t reg = make_reg(seg, oldScriptHeader ? 2 : 0);  	int objtype, objlength;  	Script *scr = segManager->getScript(seg); +	SciVersion version = segManager->sciVersion();  	// Make a pass over the object in order uninstantiate all superclasses  	objlength = 0; @@ -1792,7 +1805,7 @@ void script_uninstantiate_sci0(SegManager *segManager, SciVersion version, int s  					if (scr->getLockers())  						scr->decrementLockers();  // Decrease lockers if this is us ourselves  				} else -					script_uninstantiate(segManager, version, superclass_script); +					script_uninstantiate(segManager, superclass_script);  				// Recurse to assure that the superclass lockers number gets decreased  			} @@ -1804,7 +1817,7 @@ void script_uninstantiate_sci0(SegManager *segManager, SciVersion version, int s  	} while (objtype != 0);  } -void script_uninstantiate(SegManager *segManager, SciVersion version, int script_nr) { +void script_uninstantiate(SegManager *segManager, int script_nr) {  	SegmentId segment = segManager->segGet(script_nr);  	Script *scr = segManager->getScriptIfLoaded(segment); @@ -1824,8 +1837,8 @@ void script_uninstantiate(SegManager *segManager, SciVersion version, int script  		if (segManager->_classtable[i].reg.segment == segment)  			segManager->_classtable[i].reg = NULL_REG; -	if (version < SCI_VERSION_1_1) -		script_uninstantiate_sci0(segManager, version, script_nr, segment); +	if (segManager->sciVersion() < SCI_VERSION_1_1) +		script_uninstantiate_sci0(segManager, script_nr, segment);  	else  		warning("FIXME: Add proper script uninstantiation for SCI 1.1"); @@ -1917,8 +1930,9 @@ int game_run(EngineState **_s) {  	return 0;  } -Object *obj_get(SegManager *segManager, SciVersion version, reg_t offset) { +Object *obj_get(SegManager *segManager, reg_t offset) {  	MemObject *mobj = GET_OBJECT_SEGMENT(*segManager, offset.segment); +	SciVersion version = segManager->sciVersion();  	Object *obj = NULL;  	int idx; @@ -1941,8 +1955,9 @@ Object *obj_get(SegManager *segManager, SciVersion version, reg_t offset) {  	return obj;  } -const char *obj_get_name(SegManager *segManager, SciVersion version, reg_t pos) { -	Object *obj = obj_get(segManager, version, pos); +const char *obj_get_name(SegManager *segManager, reg_t pos) { +	Object *obj = obj_get(segManager, pos); +	SciVersion version = segManager->sciVersion();  	if (!obj)  		return "<no such object>"; @@ -1974,7 +1989,7 @@ void shrink_execution_stack(EngineState *s, uint size) {  }  reg_t* ObjVarRef::getPointer(EngineState *s) const { -	Object *o = obj_get(s->seg_manager, s->_version, obj); +	Object *o = obj_get(s->segmentManager, obj);  	if (!o) return 0;  	return &(o->_variables[varindex]);  } | 
