aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/vm.cpp')
-rw-r--r--engines/sci/engine/vm.cpp141
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]);
}