- Simplified some functions to accept only the parts of the EngineState they need as parameters, instead of the whole EngineState
- Moved the class table in the Segment manager - it's the only class using it directly - Removed the sci11 flag from save games (we already know this, we don't need to store it) - Moved script_get_segment() and get_class_address() inside the segment manager class - Removed the script_locate_by_segment wrapper - Simplified script_lookup_export() a lot by removing some paranoia checks - Added some WIP code for automatically determining the game id in the fallback detector (still not working) - General cleanup svn-id: r43458
This commit is contained in:
parent
0d4fc81698
commit
c38f58598b
14 changed files with 293 additions and 298 deletions
|
@ -889,10 +889,11 @@ bool Console::cmdRestartGame(int argc, const char **argv) {
|
||||||
|
|
||||||
bool Console::cmdClassTable(int argc, const char **argv) {
|
bool Console::cmdClassTable(int argc, const char **argv) {
|
||||||
DebugPrintf("Available classes:\n");
|
DebugPrintf("Available classes:\n");
|
||||||
for (uint i = 0; i < _vm->_gamestate->_classtable.size(); i++) {
|
for (uint i = 0; i < _vm->_gamestate->seg_manager->_classtable.size(); i++) {
|
||||||
if (_vm->_gamestate->_classtable[i].reg.segment) {
|
if (_vm->_gamestate->seg_manager->_classtable[i].reg.segment) {
|
||||||
DebugPrintf(" Class 0x%x at %04x:%04x (script 0x%x)\n", i,
|
DebugPrintf(" Class 0x%x at %04x:%04x (script 0x%x)\n", i,
|
||||||
PRINT_REG(_vm->_gamestate->_classtable[i].reg), _vm->_gamestate->_classtable[i].script);
|
PRINT_REG(_vm->_gamestate->seg_manager->_classtable[i].reg),
|
||||||
|
_vm->_gamestate->seg_manager->_classtable[i].script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1394,10 +1395,11 @@ bool Console::segmentInfo(int nr) {
|
||||||
for (uint i = 0; i < scr->_objects.size(); i++) {
|
for (uint i = 0; i < scr->_objects.size(); i++) {
|
||||||
DebugPrintf(" ");
|
DebugPrintf(" ");
|
||||||
// Object header
|
// Object header
|
||||||
Object *obj = obj_get(_vm->_gamestate, scr->_objects[i].pos);
|
Object *obj = obj_get(_vm->_gamestate->seg_manager, _vm->_gamestate->_version, scr->_objects[i].pos);
|
||||||
if (obj)
|
if (obj)
|
||||||
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(scr->_objects[i].pos),
|
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(scr->_objects[i].pos),
|
||||||
obj_get_name(_vm->_gamestate, scr->_objects[i].pos), obj->_variables.size(), obj->methods_nr);
|
obj_get_name(_vm->_gamestate->seg_manager, _vm->_gamestate->_version,
|
||||||
|
scr->_objects[i].pos), obj->_variables.size(), obj->methods_nr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1438,12 +1440,13 @@ bool Console::segmentInfo(int nr) {
|
||||||
reg_t objpos;
|
reg_t objpos;
|
||||||
objpos.offset = i;
|
objpos.offset = i;
|
||||||
objpos.segment = nr;
|
objpos.segment = nr;
|
||||||
DebugPrintf(" [%04x] %s; copy of ", i, obj_get_name(_vm->_gamestate, objpos));
|
DebugPrintf(" [%04x] %s; copy of ", i, obj_get_name(_vm->_gamestate->seg_manager, _vm->_gamestate->_version, objpos));
|
||||||
// Object header
|
// Object header
|
||||||
Object *obj = obj_get(_vm->_gamestate, ct->_table[i].pos);
|
Object *obj = obj_get(_vm->_gamestate->seg_manager, _vm->_gamestate->_version, ct->_table[i].pos);
|
||||||
if (obj)
|
if (obj)
|
||||||
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].pos),
|
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(ct->_table[i].pos),
|
||||||
obj_get_name(_vm->_gamestate, ct->_table[i].pos), obj->_variables.size(), obj->methods_nr);
|
obj_get_name(_vm->_gamestate->seg_manager, _vm->_gamestate->_version, ct->_table[i].pos),
|
||||||
|
obj->_variables.size(), obj->methods_nr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2045,7 +2048,7 @@ bool Console::cmdBacktrace(int argc, const char **argv) {
|
||||||
for (iter = _vm->_gamestate->_executionStack.begin();
|
for (iter = _vm->_gamestate->_executionStack.begin();
|
||||||
iter != _vm->_gamestate->_executionStack.end(); ++iter, ++i) {
|
iter != _vm->_gamestate->_executionStack.end(); ++iter, ++i) {
|
||||||
ExecStack &call = *iter;
|
ExecStack &call = *iter;
|
||||||
const char *objname = obj_get_name(_vm->_gamestate, call.sendp);
|
const char *objname = obj_get_name(_vm->_gamestate->seg_manager, _vm->_gamestate->_version, call.sendp);
|
||||||
int paramc, totalparamc;
|
int paramc, totalparamc;
|
||||||
|
|
||||||
switch (call.type) {
|
switch (call.type) {
|
||||||
|
@ -2187,7 +2190,7 @@ bool Console::cmdDissassemble(int argc, const char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *obj = obj_get(_vm->_gamestate, objAddr);
|
Object *obj = obj_get(_vm->_gamestate->seg_manager, _vm->_gamestate->_version, objAddr);
|
||||||
int selector_id = _vm->getKernel()->findSelector(argv[2]);
|
int selector_id = _vm->getKernel()->findSelector(argv[2]);
|
||||||
reg_t addr;
|
reg_t addr;
|
||||||
|
|
||||||
|
@ -2295,7 +2298,7 @@ bool Console::cmdSend(int argc, const char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
o = obj_get(_vm->_gamestate, object);
|
o = obj_get(_vm->_gamestate->seg_manager, _vm->_gamestate->_version, object);
|
||||||
if (o == NULL) {
|
if (o == NULL) {
|
||||||
DebugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object));
|
DebugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object));
|
||||||
return true;
|
return true;
|
||||||
|
@ -2900,7 +2903,7 @@ int parse_reg_t(EngineState *s, const char *str, reg_t *dest) { // Returns 0 on
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const char *objname = obj_get_name(s, objpos);
|
const char *objname = obj_get_name(s->seg_manager, s->_version, objpos);
|
||||||
if (!strcmp(objname, str_objname)) {
|
if (!strcmp(objname, str_objname)) {
|
||||||
// Found a match!
|
// Found a match!
|
||||||
if ((index < 0) && (times_found > 0)) {
|
if ((index < 0) && (times_found > 0)) {
|
||||||
|
@ -3042,9 +3045,10 @@ int Console::printNode(reg_t addr) {
|
||||||
|
|
||||||
int Console::printObject(reg_t pos) {
|
int Console::printObject(reg_t pos) {
|
||||||
EngineState *s = _vm->_gamestate; // for the several defines in this function
|
EngineState *s = _vm->_gamestate; // for the several defines in this function
|
||||||
Object *obj = obj_get(s, pos);
|
Object *obj = obj_get(s->seg_manager, s->_version, pos);
|
||||||
Object *var_container = obj;
|
Object *var_container = obj;
|
||||||
int i;
|
int i;
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos));
|
DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos));
|
||||||
|
@ -3052,11 +3056,11 @@ int Console::printObject(reg_t pos) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object header
|
// Object header
|
||||||
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), obj_get_name(s, pos),
|
DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), obj_get_name(s->seg_manager, s->_version, pos),
|
||||||
obj->_variables.size(), obj->methods_nr);
|
obj->_variables.size(), obj->methods_nr);
|
||||||
|
|
||||||
if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS))
|
if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS))
|
||||||
var_container = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
|
var_container = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
|
||||||
DebugPrintf(" -- member variables:\n");
|
DebugPrintf(" -- member variables:\n");
|
||||||
for (i = 0; (uint)i < obj->_variables.size(); i++) {
|
for (i = 0; (uint)i < obj->_variables.size(); i++) {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
|
@ -3068,9 +3072,9 @@ int Console::printObject(reg_t pos) {
|
||||||
reg_t val = obj->_variables[i];
|
reg_t val = obj->_variables[i];
|
||||||
DebugPrintf("%04x:%04x", PRINT_REG(val));
|
DebugPrintf("%04x:%04x", PRINT_REG(val));
|
||||||
|
|
||||||
Object *ref = obj_get(s, val);
|
Object *ref = obj_get(s->seg_manager, s->_version, val);
|
||||||
if (ref)
|
if (ref)
|
||||||
DebugPrintf(" (%s)", obj_get_name(s, val));
|
DebugPrintf(" (%s)", obj_get_name(s->seg_manager, s->_version, val));
|
||||||
|
|
||||||
DebugPrintf("\n");
|
DebugPrintf("\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "sci/sci.h"
|
#include "sci/sci.h"
|
||||||
#include "sci/exereader.h"
|
#include "sci/exereader.h"
|
||||||
|
#include "sci/engine/seg_manager.h"
|
||||||
|
|
||||||
namespace Sci {
|
namespace Sci {
|
||||||
|
|
||||||
|
@ -3086,6 +3087,19 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
|
||||||
s_fallbackDesc.desc.platform = exePlatform;
|
s_fallbackDesc.desc.platform = exePlatform;
|
||||||
s_fallbackDesc.desc.flags = ADGF_NO_FLAGS;
|
s_fallbackDesc.desc.flags = ADGF_NO_FLAGS;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Determine the game id
|
||||||
|
// TODO
|
||||||
|
ResourceManager *resMgr = new ResourceManager(256 * 1024);
|
||||||
|
SciVersion version = resMgr->sciVersion();
|
||||||
|
SegManager *segManager = new SegManager(resMgr, version);
|
||||||
|
reg_t game_obj = script_lookup_export(segManager, 0, 0);
|
||||||
|
Common::String gameName = obj_get_name(segManager,version, game_obj);
|
||||||
|
debug(2, " \"%s\" at %04x:%04x", gameName.c_str(), PRINT_REG(game_obj));
|
||||||
|
delete segManager;
|
||||||
|
delete resMgr;
|
||||||
|
#endif
|
||||||
|
|
||||||
printf("If this is *NOT* a fan-modified version (in particular, not a fan-made\n");
|
printf("If this is *NOT* a fan-modified version (in particular, not a fan-made\n");
|
||||||
printf("translation), please, report the data above, including the following\n");
|
printf("translation), please, report the data above, including the following\n");
|
||||||
printf("version number, from the game's executable:\n");
|
printf("version number, from the game's executable:\n");
|
||||||
|
|
|
@ -197,9 +197,9 @@ int create_class_table_sci11(EngineState *s) {
|
||||||
Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
|
Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
|
||||||
|
|
||||||
if (!vocab996)
|
if (!vocab996)
|
||||||
s->_classtable.resize(20);
|
s->seg_manager->_classtable.resize(20);
|
||||||
else
|
else
|
||||||
s->_classtable.resize(vocab996->size >> 2);
|
s->seg_manager->_classtable.resize(vocab996->size >> 2);
|
||||||
|
|
||||||
for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
|
for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
|
||||||
Resource *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scriptnr), 0);
|
Resource *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scriptnr), 0);
|
||||||
|
@ -213,19 +213,19 @@ int create_class_table_sci11(EngineState *s) {
|
||||||
while (READ_LE_UINT16((byte*)seeker_ptr) == SCRIPT_OBJECT_MAGIC_NUMBER) {
|
while (READ_LE_UINT16((byte*)seeker_ptr) == SCRIPT_OBJECT_MAGIC_NUMBER) {
|
||||||
if (READ_LE_UINT16((byte*)seeker_ptr + 14) & SCRIPT_INFO_CLASS) {
|
if (READ_LE_UINT16((byte*)seeker_ptr + 14) & SCRIPT_INFO_CLASS) {
|
||||||
classnr = READ_LE_UINT16((byte*)seeker_ptr + 10);
|
classnr = READ_LE_UINT16((byte*)seeker_ptr + 10);
|
||||||
if (classnr >= (int)s->_classtable.size()) {
|
if (classnr >= (int)s->seg_manager->_classtable.size()) {
|
||||||
if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
|
if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
|
||||||
warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
|
warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
|
||||||
classnr, scriptnr, scriptnr, seeker_offset);
|
classnr, scriptnr, scriptnr, seeker_offset);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->_classtable.resize(classnr + 1); // Adjust maximum number of entries
|
s->seg_manager->_classtable.resize(classnr + 1); // Adjust maximum number of entries
|
||||||
}
|
}
|
||||||
|
|
||||||
s->_classtable[classnr].reg.offset = seeker_offset;
|
s->seg_manager->_classtable[classnr].reg.offset = seeker_offset;
|
||||||
s->_classtable[classnr].reg.segment = 0;
|
s->seg_manager->_classtable[classnr].reg.segment = 0;
|
||||||
s->_classtable[classnr].script = scriptnr;
|
s->seg_manager->_classtable[classnr].script = scriptnr;
|
||||||
}
|
}
|
||||||
|
|
||||||
seeker_ptr += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
|
seeker_ptr += READ_LE_UINT16((byte*)seeker_ptr + 2) * 2;
|
||||||
|
@ -246,11 +246,12 @@ static int create_class_table_sci0(EngineState *s) {
|
||||||
int magic_offset; // For strange scripts in older SCI versions
|
int magic_offset; // For strange scripts in older SCI versions
|
||||||
|
|
||||||
Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
|
Resource *vocab996 = s->resmgr->findResource(ResourceId(kResourceTypeVocab, 996), 1);
|
||||||
|
SciVersion version = s->_version; // for the offset defines
|
||||||
|
|
||||||
if (!vocab996)
|
if (!vocab996)
|
||||||
s->_classtable.resize(20);
|
s->seg_manager->_classtable.resize(20);
|
||||||
else
|
else
|
||||||
s->_classtable.resize(vocab996->size >> 2);
|
s->seg_manager->_classtable.resize(vocab996->size >> 2);
|
||||||
|
|
||||||
for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
|
for (scriptnr = 0; scriptnr < 1000; scriptnr++) {
|
||||||
int objtype = 0;
|
int objtype = 0;
|
||||||
|
@ -270,7 +271,7 @@ static int create_class_table_sci0(EngineState *s) {
|
||||||
break;
|
break;
|
||||||
seeker += (int16)READ_LE_UINT16(script->data + seeker + 2);
|
seeker += (int16)READ_LE_UINT16(script->data + seeker + 2);
|
||||||
if (seeker <= lastseeker) {
|
if (seeker <= lastseeker) {
|
||||||
s->_classtable.clear();
|
s->seg_manager->_classtable.clear();
|
||||||
error("Script version is invalid");
|
error("Script version is invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,7 +282,7 @@ static int create_class_table_sci0(EngineState *s) {
|
||||||
seeker -= SCRIPT_OBJECT_MAGIC_OFFSET; // Adjust position; script home is base +8 bytes
|
seeker -= SCRIPT_OBJECT_MAGIC_OFFSET; // Adjust position; script home is base +8 bytes
|
||||||
|
|
||||||
classnr = (int16)READ_LE_UINT16(script->data + seeker + 4 + SCRIPT_SPECIES_OFFSET);
|
classnr = (int16)READ_LE_UINT16(script->data + seeker + 4 + SCRIPT_SPECIES_OFFSET);
|
||||||
if (classnr >= (int)s->_classtable.size()) {
|
if (classnr >= (int)s->seg_manager->_classtable.size()) {
|
||||||
|
|
||||||
if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
|
if (classnr >= SCRIPT_MAX_CLASSTABLE_SIZE) {
|
||||||
warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
|
warning("Invalid class number 0x%x in script.%d(0x%x), offset %04x",
|
||||||
|
@ -289,7 +290,7 @@ static int create_class_table_sci0(EngineState *s) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->_classtable.resize(classnr + 1); // Adjust maximum number of entries
|
s->seg_manager->_classtable.resize(classnr + 1); // Adjust maximum number of entries
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map the class ID to the script the corresponding class is contained in
|
// Map the class ID to the script the corresponding class is contained in
|
||||||
|
@ -303,9 +304,9 @@ static int create_class_table_sci0(EngineState *s) {
|
||||||
|
|
||||||
if (sugg_script == -1 || scriptnr == sugg_script /*|| !s->_classtable[classnr].reg.segment*/) {
|
if (sugg_script == -1 || scriptnr == sugg_script /*|| !s->_classtable[classnr].reg.segment*/) {
|
||||||
// Now set the home script of the class
|
// Now set the home script of the class
|
||||||
s->_classtable[classnr].reg.offset = seeker + 4 - magic_offset;
|
s->seg_manager->_classtable[classnr].reg.offset = seeker + 4 - magic_offset;
|
||||||
s->_classtable[classnr].reg.segment = 0;
|
s->seg_manager->_classtable[classnr].reg.segment = 0;
|
||||||
s->_classtable[classnr].script = scriptnr;
|
s->seg_manager->_classtable[classnr].script = scriptnr;
|
||||||
}
|
}
|
||||||
|
|
||||||
seeker += SCRIPT_OBJECT_MAGIC_OFFSET; // Re-adjust position
|
seeker += SCRIPT_OBJECT_MAGIC_OFFSET; // Re-adjust position
|
||||||
|
@ -326,6 +327,7 @@ int script_init_engine(EngineState *s) {
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
s->kernel_opt_flags = 0;
|
s->kernel_opt_flags = 0;
|
||||||
|
s->seg_manager = new SegManager(s->resmgr, s->_version);
|
||||||
|
|
||||||
if (s->_version >= SCI_VERSION_1_1)
|
if (s->_version >= SCI_VERSION_1_1)
|
||||||
result = create_class_table_sci11(s);
|
result = create_class_table_sci11(s);
|
||||||
|
@ -337,10 +339,9 @@ int script_init_engine(EngineState *s) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->seg_manager = new SegManager(s->_version >= SCI_VERSION_1_1);
|
|
||||||
s->gc_countdown = GC_INTERVAL - 1;
|
s->gc_countdown = GC_INTERVAL - 1;
|
||||||
|
|
||||||
SegmentId script_000_segment = script_get_segment(s, 0, SCRIPT_GET_LOCK);
|
SegmentId script_000_segment = s->seg_manager->getSegment(0, SCRIPT_GET_LOCK);
|
||||||
|
|
||||||
if (script_000_segment <= 0) {
|
if (script_000_segment <= 0) {
|
||||||
debug(2, "Failed to instantiate script.000");
|
debug(2, "Failed to instantiate script.000");
|
||||||
|
@ -398,7 +399,8 @@ void internal_stringfrag_strncpy(EngineState *s, reg_t *dest, reg_t *src, int le
|
||||||
void script_free_vm_memory(EngineState *s) {
|
void script_free_vm_memory(EngineState *s) {
|
||||||
debug(2, "Freeing VM memory");
|
debug(2, "Freeing VM memory");
|
||||||
|
|
||||||
s->_classtable.clear();
|
if (s->seg_manager)
|
||||||
|
s->seg_manager->_classtable.clear();
|
||||||
|
|
||||||
// Close all opened file handles
|
// Close all opened file handles
|
||||||
s->_fileHandles.clear();
|
s->_fileHandles.clear();
|
||||||
|
@ -433,14 +435,13 @@ void script_free_breakpoints(EngineState *s) {
|
||||||
|
|
||||||
int game_init(EngineState *s) {
|
int game_init(EngineState *s) {
|
||||||
// FIXME Use new VM instantiation code all over the place"
|
// FIXME Use new VM instantiation code all over the place"
|
||||||
reg_t game_obj; // Address of the game object
|
|
||||||
DataStack *stack;
|
DataStack *stack;
|
||||||
|
|
||||||
stack = s->seg_manager->allocateStack(VM_STACK_SIZE, &s->stack_segment);
|
stack = s->seg_manager->allocateStack(VM_STACK_SIZE, &s->stack_segment);
|
||||||
s->stack_base = stack->entries;
|
s->stack_base = stack->entries;
|
||||||
s->stack_top = s->stack_base + VM_STACK_SIZE;
|
s->stack_top = s->stack_base + VM_STACK_SIZE;
|
||||||
|
|
||||||
if (!script_instantiate(s, 0)) {
|
if (!script_instantiate(s->resmgr, s->seg_manager, s->_version, 0)) {
|
||||||
warning("game_init(): Could not instantiate script 0");
|
warning("game_init(): Could not instantiate script 0");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -473,20 +474,11 @@ int game_init(EngineState *s) {
|
||||||
srand(g_system->getMillis()); // Initialize random number generator
|
srand(g_system->getMillis()); // Initialize random number generator
|
||||||
|
|
||||||
// script_dissect(0, s->_selectorNames);
|
// script_dissect(0, s->_selectorNames);
|
||||||
game_obj = script_lookup_export(s, 0, 0);
|
|
||||||
// The first entry in the export table of script 0 points to the game object
|
// The first entry in the export table of script 0 points to the game object
|
||||||
|
s->game_obj = script_lookup_export(s->seg_manager, 0, 0);
|
||||||
|
s->_gameName = obj_get_name(s->seg_manager, s->_version, s->game_obj);
|
||||||
|
|
||||||
const char *tmp = obj_get_name(s, game_obj);
|
debug(2, " \"%s\" at %04x:%04x", s->_gameName.c_str(), PRINT_REG(s->game_obj));
|
||||||
|
|
||||||
if (!tmp) {
|
|
||||||
warning("Error: script.000, export 0 (%04x:%04x) does not yield an object with a name -> sanity check failed", PRINT_REG(game_obj));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
s->_gameName = tmp;
|
|
||||||
|
|
||||||
debug(2, " \"%s\" at %04x:%04x", s->_gameName.c_str(), PRINT_REG(game_obj));
|
|
||||||
|
|
||||||
s->game_obj = game_obj;
|
|
||||||
|
|
||||||
// Mark parse tree as unused
|
// Mark parse tree as unused
|
||||||
s->parser_nodes[0].type = kParseTreeLeafNode;
|
s->parser_nodes[0].type = kParseTreeLeafNode;
|
||||||
|
@ -512,7 +504,9 @@ int game_exit(EngineState *s) {
|
||||||
game_init_sound(s, SFX_STATE_FLAG_NOSOUND);
|
game_init_sound(s, SFX_STATE_FLAG_NOSOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->seg_manager->_classtable.clear();
|
||||||
delete s->seg_manager;
|
delete s->seg_manager;
|
||||||
|
s->seg_manager = 0;
|
||||||
|
|
||||||
s->_synonyms.clear();
|
s->_synonyms.clear();
|
||||||
|
|
||||||
|
|
|
@ -706,6 +706,8 @@ int determine_reg_type(EngineState *s, reg_t reg, bool allow_invalid) {
|
||||||
|
|
||||||
mobj = s->seg_manager->_heap[reg.segment];
|
mobj = s->seg_manager->_heap[reg.segment];
|
||||||
|
|
||||||
|
SciVersion version = s->_version; // for the offset defines
|
||||||
|
|
||||||
switch (mobj->getType()) {
|
switch (mobj->getType()) {
|
||||||
case MEM_OBJ_SCRIPT:
|
case MEM_OBJ_SCRIPT:
|
||||||
if (reg.offset <= (*(Script *)mobj).buf_size && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
|
if (reg.offset <= (*(Script *)mobj).buf_size && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
|
||||||
|
|
|
@ -257,7 +257,7 @@ static void bresenham_autodetect(EngineState *s) {
|
||||||
reg_t motion_class;
|
reg_t motion_class;
|
||||||
|
|
||||||
if (!parse_reg_t(s, "?Motion", &motion_class)) {
|
if (!parse_reg_t(s, "?Motion", &motion_class)) {
|
||||||
Object *obj = obj_get(s, motion_class);
|
Object *obj = obj_get(s->seg_manager, s->_version, motion_class);
|
||||||
reg_t fptr;
|
reg_t fptr;
|
||||||
byte *buf;
|
byte *buf;
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvoc
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_object(EngineState *s, reg_t object) {
|
bool is_object(EngineState *s, reg_t object) {
|
||||||
return obj_get(s, object) != NULL;
|
return obj_get(s->seg_manager, s->_version, object) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads arbitrary resources of type 'restype' with resource numbers 'resnrs'
|
// Loads arbitrary resources of type 'restype' with resource numbers 'resnrs'
|
||||||
|
@ -184,7 +184,7 @@ reg_t kResCheck(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
||||||
|
|
||||||
reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
||||||
reg_t parent_addr = argv[0];
|
reg_t parent_addr = argv[0];
|
||||||
Object *parent_obj = obj_get(s, parent_addr);
|
Object *parent_obj = obj_get(s->seg_manager, s->_version, parent_addr);
|
||||||
reg_t clone_addr;
|
reg_t clone_addr;
|
||||||
Clone *clone_obj; // same as Object*
|
Clone *clone_obj; // same as Object*
|
||||||
|
|
||||||
|
@ -205,6 +205,8 @@ reg_t kClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
||||||
*clone_obj = *parent_obj;
|
*clone_obj = *parent_obj;
|
||||||
clone_obj->flags = 0;
|
clone_obj->flags = 0;
|
||||||
|
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
// Mark as clone
|
// Mark as clone
|
||||||
clone_obj->_variables[SCRIPT_INFO_SELECTOR].offset = SCRIPT_INFO_CLONE;
|
clone_obj->_variables[SCRIPT_INFO_SELECTOR].offset = SCRIPT_INFO_CLONE;
|
||||||
clone_obj->_variables[SCRIPT_SPECIES_SELECTOR] = clone_obj->pos;
|
clone_obj->_variables[SCRIPT_SPECIES_SELECTOR] = clone_obj->pos;
|
||||||
|
@ -220,7 +222,7 @@ extern void _k_view_list_mark_free(EngineState *s, reg_t off);
|
||||||
|
|
||||||
reg_t kDisposeClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
reg_t kDisposeClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
||||||
reg_t victim_addr = argv[0];
|
reg_t victim_addr = argv[0];
|
||||||
Clone *victim_obj = obj_get(s, victim_addr);
|
Clone *victim_obj = obj_get(s->seg_manager, s->_version, victim_addr);
|
||||||
uint16 underBits;
|
uint16 underBits;
|
||||||
|
|
||||||
if (!victim_obj) {
|
if (!victim_obj) {
|
||||||
|
@ -229,6 +231,8 @@ reg_t kDisposeClone(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
||||||
return s->r_acc;
|
return s->r_acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
if (victim_obj->_variables[SCRIPT_INFO_SELECTOR].offset != SCRIPT_INFO_CLONE) {
|
if (victim_obj->_variables[SCRIPT_INFO_SELECTOR].offset != SCRIPT_INFO_CLONE) {
|
||||||
//warning("Attempt to dispose something other than a clone at %04x", offset);
|
//warning("Attempt to dispose something other than a clone at %04x", offset);
|
||||||
// SCI silently ignores this behaviour; some games actually depend on it
|
// SCI silently ignores this behaviour; some games actually depend on it
|
||||||
|
@ -260,7 +264,7 @@ reg_t kScriptID(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
||||||
int script = argv[0].toUint16();
|
int script = argv[0].toUint16();
|
||||||
int index = (argc > 1) ? argv[1].toUint16() : 0;
|
int index = (argc > 1) ? argv[1].toUint16() : 0;
|
||||||
|
|
||||||
SegmentId scriptid = script_get_segment(s, script, SCRIPT_GET_LOAD);
|
SegmentId scriptid = s->seg_manager->getSegment(script, SCRIPT_GET_LOAD);
|
||||||
Script *scr;
|
Script *scr;
|
||||||
|
|
||||||
if (argv[0].segment)
|
if (argv[0].segment)
|
||||||
|
@ -299,13 +303,13 @@ reg_t kDisposeScript(EngineState *s, int funct_nr, int argc, reg_t *argv) {
|
||||||
scr->setLockers(1);
|
scr->setLockers(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
script_uninstantiate(s, script);
|
script_uninstantiate(s->seg_manager, s->_version, script);
|
||||||
s->_executionStackPosChanged = true;
|
s->_executionStackPosChanged = true;
|
||||||
return s->r_acc;
|
return s->r_acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_heap_object(EngineState *s, reg_t pos) {
|
int is_heap_object(EngineState *s, reg_t pos) {
|
||||||
Object *obj = obj_get(s, pos);
|
Object *obj = obj_get(s->seg_manager, s->_version, pos);
|
||||||
return (obj != NULL && (!(obj->flags & OBJECT_FLAG_FREED)) && (!s->seg_manager->scriptIsMarkedAsDeleted(pos.segment)));
|
return (obj != NULL && (!(obj->flags & OBJECT_FLAG_FREED)) && (!s->seg_manager->scriptIsMarkedAsDeleted(pos.segment)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,7 @@ void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback not
|
||||||
|
|
||||||
void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
void Script::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) {
|
||||||
Script *script = this;
|
Script *script = this;
|
||||||
|
SciVersion version = s->_version; // for the offset defines
|
||||||
|
|
||||||
if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) {
|
if (addr.offset <= script->buf_size && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(script->buf + addr.offset)) {
|
||||||
int idx = RAW_GET_CLASS_INDEX(script, addr);
|
int idx = RAW_GET_CLASS_INDEX(script, addr);
|
||||||
|
|
|
@ -205,19 +205,21 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sync_SegManagerPtr(Common::Serializer &s, SegManager *&obj) {
|
static void sync_SegManagerPtr(Common::Serializer &s, SegManager *&obj) {
|
||||||
bool sci11 = false;
|
SciVersion version = SCI_VERSION_AUTODETECT;
|
||||||
|
ResourceManager *resMgr = 0;
|
||||||
|
|
||||||
if (s.isSaving()) {
|
if (s.isSaving()) {
|
||||||
assert(obj);
|
assert(obj);
|
||||||
sci11 = obj->isSci1_1;
|
version = obj->_version;
|
||||||
|
resMgr = obj->_resMgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
s.syncAsByte(sci11);
|
s.skip(1); // obsolete: used to be a flag indicating if we got sci11 or not
|
||||||
|
|
||||||
if (s.isLoading()) {
|
if (s.isLoading()) {
|
||||||
// FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch.
|
// FIXME: Do in-place loading at some point, instead of creating a new EngineState instance from scratch.
|
||||||
delete obj;
|
delete obj;
|
||||||
obj = new SegManager(sci11);
|
obj = new SegManager(resMgr, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
obj->saveLoadWithSerializer(s);
|
obj->saveLoadWithSerializer(s);
|
||||||
|
@ -266,7 +268,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
|
||||||
|
|
||||||
sync_SegManagerPtr(s, seg_manager);
|
sync_SegManagerPtr(s, seg_manager);
|
||||||
|
|
||||||
syncArray<Class>(s, _classtable);
|
syncArray<Class>(s, seg_manager->_classtable);
|
||||||
|
|
||||||
sync_sfx_state_t(s, _sound);
|
sync_sfx_state_t(s, _sound);
|
||||||
}
|
}
|
||||||
|
@ -549,7 +551,7 @@ static void load_script(EngineState *s, SegmentId seg) {
|
||||||
heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scr->nr), 0);
|
heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, scr->nr), 0);
|
||||||
|
|
||||||
memcpy(scr->buf, script->data, script->size);
|
memcpy(scr->buf, script->data, script->size);
|
||||||
if (s->seg_manager->isSci1_1)
|
if (s->seg_manager->_version == SCI_VERSION_1_1)
|
||||||
memcpy(scr->buf + scr->script_size, heap->data, heap->size);
|
memcpy(scr->buf + scr->script_size, heap->data, heap->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,6 +559,8 @@ static void load_script(EngineState *s, SegmentId seg) {
|
||||||
static void reconstruct_scripts(EngineState *s, SegManager *self) {
|
static void reconstruct_scripts(EngineState *s, SegManager *self) {
|
||||||
uint i, j;
|
uint i, j;
|
||||||
MemObject *mobj;
|
MemObject *mobj;
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
for (i = 0; i < self->_heap.size(); i++) {
|
for (i = 0; i < self->_heap.size(); i++) {
|
||||||
if (self->_heap[i]) {
|
if (self->_heap[i]) {
|
||||||
mobj = self->_heap[i];
|
mobj = self->_heap[i];
|
||||||
|
@ -567,7 +571,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
|
||||||
// FIXME: Unify this code with script_instantiate_*
|
// FIXME: Unify this code with script_instantiate_*
|
||||||
load_script(s, i);
|
load_script(s, i);
|
||||||
scr->locals_block = (scr->locals_segment == 0) ? NULL : (LocalVariables *)(s->seg_manager->_heap[scr->locals_segment]);
|
scr->locals_block = (scr->locals_segment == 0) ? NULL : (LocalVariables *)(s->seg_manager->_heap[scr->locals_segment]);
|
||||||
if (s->seg_manager->isSci1_1) {
|
if (s->seg_manager->_version == SCI_VERSION_1_1) {
|
||||||
scr->export_table = 0;
|
scr->export_table = 0;
|
||||||
scr->synonyms = 0;
|
scr->synonyms = 0;
|
||||||
if (READ_LE_UINT16(scr->buf + 6) > 0) {
|
if (READ_LE_UINT16(scr->buf + 6) > 0) {
|
||||||
|
@ -603,7 +607,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
|
||||||
for (j = 0; j < scr->_objects.size(); j++) {
|
for (j = 0; j < scr->_objects.size(); j++) {
|
||||||
byte *data = scr->buf + scr->_objects[j].pos.offset;
|
byte *data = scr->buf + scr->_objects[j].pos.offset;
|
||||||
|
|
||||||
if (self->isSci1_1) {
|
if (self->_version == SCI_VERSION_1_1) {
|
||||||
uint16 *funct_area = (uint16 *) (scr->buf + READ_LE_UINT16( data + 6 ));
|
uint16 *funct_area = (uint16 *) (scr->buf + READ_LE_UINT16( data + 6 ));
|
||||||
uint16 *prop_area = (uint16 *) (scr->buf + READ_LE_UINT16( data + 4 ));
|
uint16 *prop_area = (uint16 *) (scr->buf + READ_LE_UINT16( data + 4 ));
|
||||||
|
|
||||||
|
@ -613,7 +617,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
|
||||||
int funct_area = READ_LE_UINT16( data + SCRIPT_FUNCTAREAPTR_OFFSET );
|
int funct_area = READ_LE_UINT16( data + SCRIPT_FUNCTAREAPTR_OFFSET );
|
||||||
Object *base_obj;
|
Object *base_obj;
|
||||||
|
|
||||||
base_obj = obj_get(s, scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR]);
|
base_obj = obj_get(s->seg_manager, s->_version, scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR]);
|
||||||
|
|
||||||
if (!base_obj) {
|
if (!base_obj) {
|
||||||
warning("Object without a base class: Script %d, index %d (reg address %04x:%04x",
|
warning("Object without a base class: Script %d, index %d (reg address %04x:%04x",
|
||||||
|
@ -638,6 +642,8 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) {
|
||||||
|
|
||||||
// FIXME: The following should likely become a SegManager method
|
// FIXME: The following should likely become a SegManager method
|
||||||
static void reconstruct_clones(EngineState *s, SegManager *self) {
|
static void reconstruct_clones(EngineState *s, SegManager *self) {
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
for (uint i = 0; i < self->_heap.size(); i++) {
|
for (uint i = 0; i < self->_heap.size(); i++) {
|
||||||
if (self->_heap[i]) {
|
if (self->_heap[i]) {
|
||||||
MemObject *mobj = self->_heap[i];
|
MemObject *mobj = self->_heap[i];
|
||||||
|
@ -667,7 +673,7 @@ static void reconstruct_clones(EngineState *s, SegManager *self) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CloneTable::Entry &seeker = ct->_table[j];
|
CloneTable::Entry &seeker = ct->_table[j];
|
||||||
base_obj = obj_get(s, seeker._variables[SCRIPT_SPECIES_SELECTOR]);
|
base_obj = obj_get(s->seg_manager, s->_version, seeker._variables[SCRIPT_SPECIES_SELECTOR]);
|
||||||
if (!base_obj) {
|
if (!base_obj) {
|
||||||
printf("Clone entry without a base class: %d\n", j);
|
printf("Clone entry without a base class: %d\n", j);
|
||||||
seeker.base = seeker.base_obj = NULL;
|
seeker.base = seeker.base_obj = NULL;
|
||||||
|
@ -791,7 +797,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
|
||||||
reconstruct_scripts(retval, retval->seg_manager);
|
reconstruct_scripts(retval, retval->seg_manager);
|
||||||
reconstruct_clones(retval, retval->seg_manager);
|
reconstruct_clones(retval, retval->seg_manager);
|
||||||
retval->game_obj = s->game_obj;
|
retval->game_obj = s->game_obj;
|
||||||
retval->script_000 = retval->seg_manager->getScript(script_get_segment(s, 0, SCRIPT_GET_DONT_LOAD));
|
retval->script_000 = retval->seg_manager->getScript(retval->seg_manager->getSegment(0, SCRIPT_GET_DONT_LOAD));
|
||||||
retval->gc_countdown = GC_INTERVAL - 1;
|
retval->gc_countdown = GC_INTERVAL - 1;
|
||||||
retval->sys_strings_segment = find_unique_seg_by_type(retval->seg_manager, MEM_OBJ_SYS_STRINGS);
|
retval->sys_strings_segment = find_unique_seg_by_type(retval->seg_manager, MEM_OBJ_SYS_STRINGS);
|
||||||
retval->sys_strings = (SystemStrings *)GET_SEGMENT(*retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS);
|
retval->sys_strings = (SystemStrings *)GET_SEGMENT(*retval->seg_manager, retval->sys_strings_segment, MEM_OBJ_SYS_STRINGS);
|
||||||
|
@ -831,7 +837,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) {
|
||||||
|
|
||||||
retval->successor = NULL;
|
retval->successor = NULL;
|
||||||
retval->pic_priority_table = (int *)gfxop_get_pic_metainfo(retval->gfx_state);
|
retval->pic_priority_table = (int *)gfxop_get_pic_metainfo(retval->gfx_state);
|
||||||
retval->_gameName = obj_get_name(retval, retval->game_obj);
|
retval->_gameName = obj_get_name(retval->seg_manager, retval->_version, retval->game_obj);
|
||||||
|
|
||||||
retval->_sound._it = NULL;
|
retval->_sound._it = NULL;
|
||||||
retval->_sound._flags = s->_sound._flags;
|
retval->_sound._flags = s->_sound._flags;
|
||||||
|
|
|
@ -37,9 +37,10 @@ extern const char *selector_name(EngineState *s, int selector);
|
||||||
ScriptState scriptState;
|
ScriptState scriptState;
|
||||||
|
|
||||||
int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) {
|
int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) {
|
||||||
Object *obj = obj_get(s, objp);
|
Object *obj = obj_get(s->seg_manager, s->_version, objp);
|
||||||
byte *selectoroffset;
|
byte *selectoroffset;
|
||||||
int selectors;
|
int selectors;
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
warning("Applied propertyOffsetToId on non-object at %04x:%04x", PRINT_REG(objp));
|
warning("Applied propertyOffsetToId on non-object at %04x:%04x", PRINT_REG(objp));
|
||||||
|
@ -52,7 +53,7 @@ int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) {
|
||||||
selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;
|
selectoroffset = ((byte *)(obj->base_obj)) + SCRIPT_SELECTOR_OFFSET + selectors * 2;
|
||||||
else {
|
else {
|
||||||
if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) {
|
if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) {
|
||||||
obj = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
|
obj = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
|
||||||
selectoroffset = (byte *)obj->base_vars;
|
selectoroffset = (byte *)obj->base_vars;
|
||||||
} else
|
} else
|
||||||
selectoroffset = (byte *)obj->base_vars;
|
selectoroffset = (byte *)obj->base_vars;
|
||||||
|
@ -268,7 +269,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
|
||||||
|
|
||||||
selector = sb[- stackframe].offset;
|
selector = sb[- stackframe].offset;
|
||||||
|
|
||||||
name = obj_get_name(s, called_obj_addr);
|
name = obj_get_name(s->seg_manager, s->_version, called_obj_addr);
|
||||||
|
|
||||||
if (!name)
|
if (!name)
|
||||||
name = "<invalid>";
|
name = "<invalid>";
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace Sci {
|
||||||
|
|
||||||
#define INVALID_SCRIPT_ID -1
|
#define INVALID_SCRIPT_ID -1
|
||||||
|
|
||||||
SegManager::SegManager(bool sci1_1) {
|
SegManager::SegManager(ResourceManager *resMgr, SciVersion version) {
|
||||||
id_seg_map = new IntMapper();
|
id_seg_map = new IntMapper();
|
||||||
reserved_id = INVALID_SCRIPT_ID;
|
reserved_id = INVALID_SCRIPT_ID;
|
||||||
id_seg_map->checkKey(reserved_id, true); // reserve entry 0 for INVALID_SCRIPT_ID
|
id_seg_map->checkKey(reserved_id, true); // reserve entry 0 for INVALID_SCRIPT_ID
|
||||||
|
@ -66,7 +66,8 @@ SegManager::SegManager(bool sci1_1) {
|
||||||
Hunks_seg_id = 0;
|
Hunks_seg_id = 0;
|
||||||
|
|
||||||
exports_wide = 0;
|
exports_wide = 0;
|
||||||
isSci1_1 = sci1_1;
|
_version = version;
|
||||||
|
_resMgr = resMgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the object, free the memorys if allocated before
|
// Destroy the object, free the memorys if allocated before
|
||||||
|
@ -109,7 +110,7 @@ MemObject *SegManager::allocNonscriptSegment(MemObjectType type, SegmentId *segi
|
||||||
// Returns : 0 - allocation failure
|
// Returns : 0 - allocation failure
|
||||||
// 1 - allocated successfully
|
// 1 - allocated successfully
|
||||||
// seg_id - allocated segment id
|
// seg_id - allocated segment id
|
||||||
Script *SegManager::allocateScript(EngineState *s, int script_nr, SegmentId *seg_id) {
|
Script *SegManager::allocateScript(int script_nr, SegmentId *seg_id) {
|
||||||
bool was_added;
|
bool was_added;
|
||||||
MemObject *mem;
|
MemObject *mem;
|
||||||
|
|
||||||
|
@ -128,20 +129,20 @@ Script *SegManager::allocateScript(EngineState *s, int script_nr, SegmentId *seg
|
||||||
return (Script *)mem;
|
return (Script *)mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) {
|
void SegManager::setScriptSize(Script &scr, int script_nr) {
|
||||||
Resource *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
|
Resource *script = _resMgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
|
||||||
Resource *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
|
Resource *heap = _resMgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
|
||||||
|
|
||||||
scr.script_size = script->size;
|
scr.script_size = script->size;
|
||||||
scr.heap_size = 0; // Set later
|
scr.heap_size = 0; // Set later
|
||||||
|
|
||||||
if (!script || (s->_version >= SCI_VERSION_1_1 && !heap)) {
|
if (!script || (_version >= SCI_VERSION_1_1 && !heap)) {
|
||||||
error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap");
|
error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap");
|
||||||
}
|
}
|
||||||
if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) {
|
if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) {
|
||||||
scr.buf_size = script->size + READ_LE_UINT16(script->data) * 2;
|
scr.buf_size = script->size + READ_LE_UINT16(script->data) * 2;
|
||||||
//locals_size = READ_LE_UINT16(script->data) * 2;
|
//locals_size = READ_LE_UINT16(script->data) * 2;
|
||||||
} else if (s->_version < SCI_VERSION_1_1) {
|
} else if (_version < SCI_VERSION_1_1) {
|
||||||
scr.buf_size = script->size;
|
scr.buf_size = script->size;
|
||||||
} else {
|
} else {
|
||||||
scr.buf_size = script->size + heap->size;
|
scr.buf_size = script->size + heap->size;
|
||||||
|
@ -163,10 +164,10 @@ void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) {
|
int SegManager::initialiseScript(Script &scr, int script_nr) {
|
||||||
// allocate the script.buf
|
// allocate the script.buf
|
||||||
|
|
||||||
setScriptSize(scr, s, script_nr);
|
setScriptSize(scr, script_nr);
|
||||||
scr.buf = (byte *)malloc(scr.buf_size);
|
scr.buf = (byte *)malloc(scr.buf_size);
|
||||||
|
|
||||||
#ifdef DEBUG_SEG_MANAGER
|
#ifdef DEBUG_SEG_MANAGER
|
||||||
|
@ -191,7 +192,7 @@ int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) {
|
||||||
|
|
||||||
scr.obj_indices = new IntMapper();
|
scr.obj_indices = new IntMapper();
|
||||||
|
|
||||||
if (s->_version >= SCI_VERSION_1_1)
|
if (_version >= SCI_VERSION_1_1)
|
||||||
scr.heap_start = scr.buf + scr.script_size;
|
scr.heap_start = scr.buf + scr.script_size;
|
||||||
else
|
else
|
||||||
scr.heap_start = scr.buf;
|
scr.heap_start = scr.buf;
|
||||||
|
@ -319,7 +320,7 @@ int SegManager::relocateBlock(Common::Array<reg_t> &block, int block_location, S
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
block[idx].segment = segment; // Perform relocation
|
block[idx].segment = segment; // Perform relocation
|
||||||
if (isSci1_1)
|
if (_version == SCI_VERSION_1_1)
|
||||||
block[idx].offset += getScript(segment)->script_size;
|
block[idx].offset += getScript(segment)->script_size;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -429,13 +430,51 @@ void SegManager::heapRelocate(reg_t block) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INST_LOOKUP_CLASS(id) ((id == 0xffff) ? NULL_REG : get_class_address(s, id, SCRIPT_GET_LOCK, NULL_REG))
|
SegmentId SegManager::getSegment(int script_nr, SCRIPT_GET load) {
|
||||||
|
SegmentId segment;
|
||||||
|
|
||||||
reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller);
|
if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD)
|
||||||
|
script_instantiate(_resMgr, this, _version, script_nr);
|
||||||
|
|
||||||
Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) {
|
segment = segGet(script_nr);
|
||||||
|
|
||||||
|
if (segment > 0) {
|
||||||
|
if ((load & SCRIPT_GET_LOCK) == SCRIPT_GET_LOCK)
|
||||||
|
getScript(segment)->incrementLockers();
|
||||||
|
|
||||||
|
return segment;
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INST_LOOKUP_CLASS(id) ((id == 0xffff) ? NULL_REG : get_class_address(id, SCRIPT_GET_LOCK, NULL_REG))
|
||||||
|
|
||||||
|
reg_t SegManager::get_class_address(int classnr, SCRIPT_GET lock, reg_t caller) {
|
||||||
|
if (classnr < 0 || (int)_classtable.size() <= classnr || _classtable[classnr].script < 0) {
|
||||||
|
error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, _classtable.size());
|
||||||
|
return NULL_REG;
|
||||||
|
} else {
|
||||||
|
Class *the_class = &_classtable[classnr];
|
||||||
|
if (!the_class->reg.segment) {
|
||||||
|
getSegment(the_class->script, lock);
|
||||||
|
|
||||||
|
if (!the_class->reg.segment) {
|
||||||
|
error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;"
|
||||||
|
" Entering debugger.", classnr, the_class->script, the_class->script);
|
||||||
|
return NULL_REG;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (caller.segment != the_class->reg.segment)
|
||||||
|
getScript(the_class->reg.segment)->incrementLockers();
|
||||||
|
|
||||||
|
return the_class->reg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *SegManager::scriptObjInit0(reg_t obj_pos) {
|
||||||
Object *obj;
|
Object *obj;
|
||||||
int id;
|
int id;
|
||||||
|
SciVersion version = _version; // for the offset defines
|
||||||
unsigned int base = obj_pos.offset - SCRIPT_OBJECT_MAGIC_OFFSET;
|
unsigned int base = obj_pos.offset - SCRIPT_OBJECT_MAGIC_OFFSET;
|
||||||
reg_t temp;
|
reg_t temp;
|
||||||
|
|
||||||
|
@ -489,7 +528,7 @@ Object *SegManager::scriptObjInit0(EngineState *s, reg_t obj_pos) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *SegManager::scriptObjInit11(EngineState *s, reg_t obj_pos) {
|
Object *SegManager::scriptObjInit11(reg_t obj_pos) {
|
||||||
Object *obj;
|
Object *obj;
|
||||||
int id;
|
int id;
|
||||||
int base = obj_pos.offset;
|
int base = obj_pos.offset;
|
||||||
|
@ -543,11 +582,11 @@ Object *SegManager::scriptObjInit11(EngineState *s, reg_t obj_pos) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *SegManager::scriptObjInit(EngineState *s, reg_t obj_pos) {
|
Object *SegManager::scriptObjInit(reg_t obj_pos) {
|
||||||
if (!isSci1_1)
|
if (_version != SCI_VERSION_1_1)
|
||||||
return scriptObjInit0(s, obj_pos);
|
return scriptObjInit0(obj_pos);
|
||||||
else
|
else
|
||||||
return scriptObjInit11(s, obj_pos);
|
return scriptObjInit11(obj_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) {
|
LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) {
|
||||||
|
@ -588,7 +627,7 @@ void SegManager::scriptInitialiseLocals(reg_t location) {
|
||||||
|
|
||||||
VERIFY(location.offset + 1 < (uint16)scr->buf_size, "Locals beyond end of script\n");
|
VERIFY(location.offset + 1 < (uint16)scr->buf_size, "Locals beyond end of script\n");
|
||||||
|
|
||||||
if (isSci1_1)
|
if (_version == SCI_VERSION_1_1)
|
||||||
count = READ_LE_UINT16(scr->buf + location.offset - 2);
|
count = READ_LE_UINT16(scr->buf + location.offset - 2);
|
||||||
else
|
else
|
||||||
count = (READ_LE_UINT16(scr->buf + location.offset - 2) - 4) >> 1;
|
count = (READ_LE_UINT16(scr->buf + location.offset - 2) - 4) >> 1;
|
||||||
|
@ -627,24 +666,25 @@ void SegManager::scriptRelocateExportsSci11(SegmentId seg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SegManager::scriptInitialiseObjectsSci11(EngineState *s, SegmentId seg) {
|
void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) {
|
||||||
Script *scr = getScript(seg);
|
Script *scr = getScript(seg);
|
||||||
byte *seeker = scr->heap_start + 4 + READ_LE_UINT16(scr->heap_start + 2) * 2;
|
byte *seeker = scr->heap_start + 4 + READ_LE_UINT16(scr->heap_start + 2) * 2;
|
||||||
|
SciVersion version = _version; // for the selector defines
|
||||||
|
|
||||||
while (READ_LE_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) {
|
while (READ_LE_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) {
|
||||||
if (READ_LE_UINT16(seeker + 14) & SCRIPT_INFO_CLASS) {
|
if (READ_LE_UINT16(seeker + 14) & SCRIPT_INFO_CLASS) {
|
||||||
int classpos = seeker - scr->buf;
|
int classpos = seeker - scr->buf;
|
||||||
int species = READ_LE_UINT16(seeker + 10);
|
int species = READ_LE_UINT16(seeker + 10);
|
||||||
|
|
||||||
if (species < 0 || species >= (int)s->_classtable.size()) {
|
if (species < 0 || species >= (int)_classtable.size()) {
|
||||||
error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d\n",
|
error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d\n",
|
||||||
species, species, s->_classtable.size(), scr->nr);
|
species, species, _classtable.size(), scr->nr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->_classtable[species].script = scr->nr;
|
_classtable[species].script = scr->nr;
|
||||||
s->_classtable[species].reg.segment = seg;
|
_classtable[species].reg.segment = seg;
|
||||||
s->_classtable[species].reg.offset = classpos;
|
_classtable[species].reg.offset = classpos;
|
||||||
}
|
}
|
||||||
seeker += READ_LE_UINT16(seeker + 2) * 2;
|
seeker += READ_LE_UINT16(seeker + 2) * 2;
|
||||||
}
|
}
|
||||||
|
@ -656,12 +696,12 @@ void SegManager::scriptInitialiseObjectsSci11(EngineState *s, SegmentId seg) {
|
||||||
|
|
||||||
reg.segment = seg;
|
reg.segment = seg;
|
||||||
reg.offset = seeker - scr->buf;
|
reg.offset = seeker - scr->buf;
|
||||||
obj = scriptObjInit(s, reg);
|
obj = scriptObjInit(reg);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (obj->_variables[5].offset != 0xffff) {
|
if (obj->_variables[5].offset != 0xffff) {
|
||||||
obj->_variables[5] = INST_LOOKUP_CLASS(obj->_variables[5].offset);
|
obj->_variables[5] = INST_LOOKUP_CLASS(obj->_variables[5].offset);
|
||||||
base_obj = obj_get(s, obj->_variables[5]);
|
base_obj = obj_get(s->seg_manager, s->_version, obj->_variables[5]);
|
||||||
obj->variable_names_nr = base_obj->variables_nr;
|
obj->variable_names_nr = base_obj->variables_nr;
|
||||||
obj->base_obj = base_obj->base_obj;
|
obj->base_obj = base_obj->base_obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,12 +43,22 @@ namespace Sci {
|
||||||
(((mgr)._heap[index] && ((mgr)._heap[index]->getType() == MEM_OBJ_SCRIPT || (mgr)._heap[index]->getType() == MEM_OBJ_CLONES))? (mgr)._heap[index] \
|
(((mgr)._heap[index] && ((mgr)._heap[index]->getType() == MEM_OBJ_SCRIPT || (mgr)._heap[index]->getType() == MEM_OBJ_CLONES))? (mgr)._heap[index] \
|
||||||
: NULL): NULL)
|
: NULL): NULL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for getSegment()
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
SCRIPT_GET_DONT_LOAD = 0, /**< Fail if not loaded */
|
||||||
|
SCRIPT_GET_LOAD = 1, /**< Load, if neccessary */
|
||||||
|
SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */
|
||||||
|
} SCRIPT_GET;
|
||||||
|
|
||||||
|
|
||||||
class SegManager : public Common::Serializable {
|
class SegManager : public Common::Serializable {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Initialize the segment manager
|
* Initialize the segment manager
|
||||||
*/
|
*/
|
||||||
SegManager(bool sci1_1);
|
SegManager(ResourceManager *resMgr, SciVersion version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deallocate all memory associated with the segment manager
|
* Deallocate all memory associated with the segment manager
|
||||||
|
@ -61,14 +71,12 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a script into the segment manager
|
* Allocate a script into the segment manager
|
||||||
* @param s The state containing resource manager
|
|
||||||
* handlers to load the script data
|
|
||||||
* @param script_nr The number of the script to load
|
* @param script_nr The number of the script to load
|
||||||
* @param seg_id The segment ID of the newly allocated segment,
|
* @param seg_id The segment ID of the newly allocated segment,
|
||||||
* on success
|
* on success
|
||||||
* @return 0 on failure, 1 on success
|
* @return 0 on failure, 1 on success
|
||||||
*/
|
*/
|
||||||
Script *allocateScript(EngineState *s, int script_nr, SegmentId *seg_id);
|
Script *allocateScript(int script_nr, SegmentId *seg_id);
|
||||||
|
|
||||||
// The script must then be initialised; see section (1b.), below.
|
// The script must then be initialised; see section (1b.), below.
|
||||||
|
|
||||||
|
@ -154,7 +162,7 @@ public:
|
||||||
* @returns A newly created Object describing the object,
|
* @returns A newly created Object describing the object,
|
||||||
* stored within the relevant script
|
* stored within the relevant script
|
||||||
*/
|
*/
|
||||||
Object *scriptObjInit(EngineState *s, reg_t obj_pos);
|
Object *scriptObjInit(reg_t obj_pos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs the segment manager that a code block must be relocated
|
* Informs the segment manager that a code block must be relocated
|
||||||
|
@ -317,13 +325,20 @@ public:
|
||||||
*/
|
*/
|
||||||
byte *dereference(reg_t reg, int *size);
|
byte *dereference(reg_t reg, int *size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the segment occupied by a certain script
|
||||||
|
* @param[in] script_id The script in question
|
||||||
|
* @param[in] load One of SCRIPT_GET_*
|
||||||
|
* @return The script's segment, or 0 on failure
|
||||||
|
*/
|
||||||
|
SegmentId getSegment(int script_nr, SCRIPT_GET load);
|
||||||
|
reg_t get_class_address(int classnr, SCRIPT_GET lock, reg_t caller);
|
||||||
|
|
||||||
|
|
||||||
void heapRelocate(reg_t block);
|
void heapRelocate(reg_t block);
|
||||||
void scriptRelocateExportsSci11(SegmentId seg);
|
void scriptRelocateExportsSci11(SegmentId seg);
|
||||||
void scriptInitialiseObjectsSci11(EngineState *s, SegmentId seg);
|
void scriptInitialiseObjectsSci11(SegmentId seg);
|
||||||
int initialiseScript(Script &scr, EngineState *s, int script_nr);
|
int initialiseScript(Script &scr, int script_nr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IntMapper *id_seg_map; ///< id - script id; seg - index of heap
|
IntMapper *id_seg_map; ///< id - script id; seg - index of heap
|
||||||
|
@ -331,7 +346,9 @@ public: // TODO: make private
|
||||||
Common::Array<MemObject *> _heap;
|
Common::Array<MemObject *> _heap;
|
||||||
int reserved_id;
|
int reserved_id;
|
||||||
int exports_wide;
|
int exports_wide;
|
||||||
bool isSci1_1;
|
SciVersion _version;
|
||||||
|
ResourceManager *_resMgr;
|
||||||
|
Common::Array<Class> _classtable; /**< Table of all classes */
|
||||||
|
|
||||||
SegmentId Clones_seg_id; ///< ID of the (a) clones segment
|
SegmentId Clones_seg_id; ///< ID of the (a) clones segment
|
||||||
SegmentId Lists_seg_id; ///< ID of the (a) list segment
|
SegmentId Lists_seg_id; ///< ID of the (a) list segment
|
||||||
|
@ -351,9 +368,9 @@ private:
|
||||||
int relocateObject(Object *obj, SegmentId segment, int location);
|
int relocateObject(Object *obj, SegmentId segment, int location);
|
||||||
|
|
||||||
int findFreeId(int *id);
|
int findFreeId(int *id);
|
||||||
static void setScriptSize(Script &scr, EngineState *s, int script_nr);
|
void setScriptSize(Script &scr, int script_nr);
|
||||||
Object *scriptObjInit0(EngineState *s, reg_t obj_pos);
|
Object *scriptObjInit0(reg_t obj_pos);
|
||||||
Object *scriptObjInit11(EngineState *s, reg_t obj_pos);
|
Object *scriptObjInit11(reg_t obj_pos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check segment validity
|
* Check segment validity
|
||||||
|
|
|
@ -291,8 +291,6 @@ public:
|
||||||
|
|
||||||
reg_t game_obj; /**< Pointer to the game object */
|
reg_t game_obj; /**< Pointer to the game object */
|
||||||
|
|
||||||
Common::Array<Class> _classtable; /**< Table of all classes */
|
|
||||||
|
|
||||||
SegManager *seg_manager;
|
SegManager *seg_manager;
|
||||||
int gc_countdown; /**< Number of kernel calls until next gc */
|
int gc_countdown; /**< Number of kernel calls until next gc */
|
||||||
|
|
||||||
|
|
|
@ -187,34 +187,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
|
||||||
|
|
||||||
#define OBJ_PROPERTY(o, p) (validate_property(o, p))
|
#define OBJ_PROPERTY(o, p) (validate_property(o, p))
|
||||||
|
|
||||||
reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller) {
|
|
||||||
|
|
||||||
if (NULL == s) {
|
|
||||||
warning("vm.c: get_class_address(): NULL passed for \"s\"");
|
|
||||||
return NULL_REG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (classnr < 0 || (int)s->_classtable.size() <= classnr || s->_classtable[classnr].script < 0) {
|
|
||||||
error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, s->_classtable.size());
|
|
||||||
return NULL_REG;
|
|
||||||
} else {
|
|
||||||
Class *the_class = &s->_classtable[classnr];
|
|
||||||
if (!the_class->reg.segment) {
|
|
||||||
script_get_segment(s, the_class->script, lock);
|
|
||||||
|
|
||||||
if (!the_class->reg.segment) {
|
|
||||||
error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;"
|
|
||||||
" Entering debugger.", classnr, the_class->script, the_class->script);
|
|
||||||
return NULL_REG;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
if (caller.segment != the_class->reg.segment)
|
|
||||||
s->seg_manager->getScript(the_class->reg.segment)->incrementLockers();
|
|
||||||
|
|
||||||
return the_class->reg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operating on the stack
|
// Operating on the stack
|
||||||
// 16 bit:
|
// 16 bit:
|
||||||
#define PUSH(v) PUSH32(make_reg(0, v))
|
#define PUSH(v) PUSH32(make_reg(0, v))
|
||||||
|
@ -236,7 +208,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
|
||||||
Script *scr = s->seg_manager->getScriptIfLoaded(seg);
|
Script *scr = s->seg_manager->getScriptIfLoaded(seg);
|
||||||
|
|
||||||
if (!scr) // Script not present yet?
|
if (!scr) // Script not present yet?
|
||||||
seg = script_instantiate(s, script);
|
seg = script_instantiate(s->resmgr, s->seg_manager, s->_version, script);
|
||||||
else
|
else
|
||||||
scr->unmarkDeleted();
|
scr->unmarkDeleted();
|
||||||
|
|
||||||
|
@ -313,7 +285,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
|
||||||
Breakpoint *bp;
|
Breakpoint *bp;
|
||||||
char method_name [256];
|
char method_name [256];
|
||||||
|
|
||||||
sprintf(method_name, "%s::%s", obj_get_name(s, send_obj), ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector).c_str());
|
sprintf(method_name, "%s::%s", obj_get_name(s->seg_manager, s->_version, send_obj), ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector).c_str());
|
||||||
|
|
||||||
bp = s->bp_list;
|
bp = s->bp_list;
|
||||||
while (bp) {
|
while (bp) {
|
||||||
|
@ -501,10 +473,6 @@ void vm_handle_fatal_error(EngineState *s, int line, const char *file) {
|
||||||
error("Fatal VM error in %s, L%d; aborting...", file, line);
|
error("Fatal VM error in %s, L%d; aborting...", file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Script *script_locate_by_segment(EngineState *s, SegmentId seg) {
|
|
||||||
return s->seg_manager->getScriptIfLoaded(seg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static reg_t pointer_add(EngineState *s, reg_t base, int offset) {
|
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->seg_manager, base.segment);
|
||||||
|
|
||||||
|
@ -559,8 +527,8 @@ void run_vm(EngineState *s, int restoring) {
|
||||||
// Current execution data:
|
// Current execution data:
|
||||||
scriptState.xs = &(s->_executionStack.back());
|
scriptState.xs = &(s->_executionStack.back());
|
||||||
ExecStack *xs_new = NULL;
|
ExecStack *xs_new = NULL;
|
||||||
Object *obj = obj_get(s, scriptState.xs->objp);
|
Object *obj = obj_get(s->seg_manager, s->_version, scriptState.xs->objp);
|
||||||
Script *local_script = script_locate_by_segment(s, scriptState.xs->local_segment);
|
Script *local_script = s->seg_manager->getScriptIfLoaded(scriptState.xs->local_segment);
|
||||||
int old_execution_stack_base = s->execution_stack_base;
|
int old_execution_stack_base = s->execution_stack_base;
|
||||||
// Used to detect the stack bottom, for "physical" returns
|
// Used to detect the stack bottom, for "physical" returns
|
||||||
const byte *code_buf = NULL; // (Avoid spurious warning)
|
const byte *code_buf = NULL; // (Avoid spurious warning)
|
||||||
|
@ -606,7 +574,7 @@ void run_vm(EngineState *s, int restoring) {
|
||||||
scriptState.xs = &(s->_executionStack.back());
|
scriptState.xs = &(s->_executionStack.back());
|
||||||
s->_executionStackPosChanged = false;
|
s->_executionStackPosChanged = false;
|
||||||
|
|
||||||
scr = script_locate_by_segment(s, scriptState.xs->addr.pc.segment);
|
scr = s->seg_manager->getScriptIfLoaded(scriptState.xs->addr.pc.segment);
|
||||||
if (!scr) {
|
if (!scr) {
|
||||||
// No script? Implicit return via fake instruction buffer
|
// No script? Implicit return via fake instruction buffer
|
||||||
warning("Running on non-existant script in segment %x", scriptState.xs->addr.pc.segment);
|
warning("Running on non-existant script in segment %x", scriptState.xs->addr.pc.segment);
|
||||||
|
@ -619,12 +587,12 @@ void run_vm(EngineState *s, int restoring) {
|
||||||
scr = NULL;
|
scr = NULL;
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
} else {
|
} else {
|
||||||
obj = obj_get(s, scriptState.xs->objp);
|
obj = obj_get(s->seg_manager, s->_version, scriptState.xs->objp);
|
||||||
code_buf = scr->buf;
|
code_buf = scr->buf;
|
||||||
#ifndef DISABLE_VALIDATIONS
|
#ifndef DISABLE_VALIDATIONS
|
||||||
code_buf_size = scr->buf_size;
|
code_buf_size = scr->buf_size;
|
||||||
#endif
|
#endif
|
||||||
local_script = script_locate_by_segment(s, scriptState.xs->local_segment);
|
local_script = s->seg_manager->getScriptIfLoaded(scriptState.xs->local_segment);
|
||||||
if (!local_script) {
|
if (!local_script) {
|
||||||
warning("Could not find local script from segment %x", scriptState.xs->local_segment);
|
warning("Could not find local script from segment %x", scriptState.xs->local_segment);
|
||||||
local_script = NULL;
|
local_script = NULL;
|
||||||
|
@ -1077,7 +1045,7 @@ void run_vm(EngineState *s, int restoring) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x28: // class
|
case 0x28: // class
|
||||||
s->r_acc = get_class_address(s, (unsigned)opparams[0], SCRIPT_GET_LOCK,
|
s->r_acc = s->seg_manager->get_class_address((unsigned)opparams[0], SCRIPT_GET_LOCK,
|
||||||
scriptState.xs->addr.pc);
|
scriptState.xs->addr.pc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1097,7 +1065,7 @@ void run_vm(EngineState *s, int restoring) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x2b: // super
|
case 0x2b: // super
|
||||||
r_temp = get_class_address(s, opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc);
|
r_temp = s->seg_manager->get_class_address(opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc);
|
||||||
|
|
||||||
if (!r_temp.segment)
|
if (!r_temp.segment)
|
||||||
error("[VM]: Invalid superclass in object");
|
error("[VM]: Invalid superclass in object");
|
||||||
|
@ -1432,6 +1400,7 @@ void run_vm(EngineState *s, int restoring) {
|
||||||
static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) {
|
static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) {
|
||||||
// Determines if obj explicitly defines slc as a varselector
|
// Determines if obj explicitly defines slc as a varselector
|
||||||
// Returns -1 if not found
|
// Returns -1 if not found
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
if (s->_version < SCI_VERSION_1_1) {
|
if (s->_version < SCI_VERSION_1_1) {
|
||||||
int varnum = obj->variable_names_nr;
|
int varnum = obj->variable_names_nr;
|
||||||
|
@ -1452,7 +1421,7 @@ static int _obj_locate_varselector(EngineState *s, Object *obj, Selector slc) {
|
||||||
int varnum = obj->_variables[1].offset;
|
int varnum = obj->_variables[1].offset;
|
||||||
|
|
||||||
if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS))
|
if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS))
|
||||||
buf = ((byte *) obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR])->base_vars);
|
buf = ((byte *) obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR])->base_vars);
|
||||||
|
|
||||||
for (i = 0; i < varnum; i++)
|
for (i = 0; i < varnum; i++)
|
||||||
if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it?
|
if (READ_LE_UINT16(buf + (i << 1)) == slc) // Found it?
|
||||||
|
@ -1478,6 +1447,7 @@ static int _class_locate_funcselector(EngineState *s, Object *obj, Selector slc)
|
||||||
|
|
||||||
static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object *obj, Selector selector_id, reg_t *fptr) {
|
static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object *obj, Selector selector_id, reg_t *fptr) {
|
||||||
int index;
|
int index;
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
// "recursive" lookup
|
// "recursive" lookup
|
||||||
|
|
||||||
|
@ -1492,7 +1462,7 @@ static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object
|
||||||
return kSelectorMethod;
|
return kSelectorMethod;
|
||||||
} else {
|
} else {
|
||||||
seg_id = obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].segment;
|
seg_id = obj->_variables[SCRIPT_SUPERCLASS_SELECTOR].segment;
|
||||||
obj = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
|
obj = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1500,9 +1470,10 @@ static SelectorType _lookup_selector_function(EngineState *s, int seg_id, Object
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) {
|
SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector selector_id, ObjVarRef *varp, reg_t *fptr) {
|
||||||
Object *obj = obj_get(s, obj_location);
|
Object *obj = obj_get(s->seg_manager, s->_version, obj_location);
|
||||||
Object *species;
|
Object *species;
|
||||||
int index;
|
int index;
|
||||||
|
SciVersion version = s->_version; // for the selector defines
|
||||||
|
|
||||||
// Early SCI versions used the LSB in the selector ID as a read/write
|
// Early SCI versions used the LSB in the selector ID as a read/write
|
||||||
// toggle, meaning that we must remove it for selector lookup.
|
// toggle, meaning that we must remove it for selector lookup.
|
||||||
|
@ -1517,7 +1488,7 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select
|
||||||
if (IS_CLASS(obj))
|
if (IS_CLASS(obj))
|
||||||
species = obj;
|
species = obj;
|
||||||
else
|
else
|
||||||
species = obj_get(s, obj->_variables[SCRIPT_SPECIES_SELECTOR]);
|
species = obj_get(s->seg_manager, s->_version, obj->_variables[SCRIPT_SPECIES_SELECTOR]);
|
||||||
|
|
||||||
|
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
|
@ -1540,65 +1511,27 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select
|
||||||
return _lookup_selector_function(s, obj_location.segment, obj, selector_id, fptr);
|
return _lookup_selector_function(s, obj_location.segment, obj, selector_id, fptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SegmentId script_get_segment(EngineState *s, int script_nr, SCRIPT_GET load) {
|
reg_t script_lookup_export(SegManager *segManager, int script_nr, int export_index) {
|
||||||
SegmentId segment;
|
SegmentId seg = segManager->getSegment(script_nr, SCRIPT_GET_DONT_LOAD);
|
||||||
|
Script *script = segManager->getScriptIfLoaded(seg);
|
||||||
if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD)
|
|
||||||
script_instantiate(s, script_nr);
|
|
||||||
|
|
||||||
segment = s->seg_manager->segGet(script_nr);
|
|
||||||
|
|
||||||
if (segment > 0) {
|
|
||||||
if ((load & SCRIPT_GET_LOCK) == SCRIPT_GET_LOCK)
|
|
||||||
s->seg_manager->getScript(segment)->incrementLockers();
|
|
||||||
|
|
||||||
return segment;
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_t script_lookup_export(EngineState *s, int script_nr, int export_index) {
|
|
||||||
SegmentId seg = script_get_segment(s, script_nr, SCRIPT_GET_DONT_LOAD);
|
|
||||||
Script *script = NULL;
|
|
||||||
|
|
||||||
#ifndef DISABLE_VALIDATIONS
|
|
||||||
if (!seg)
|
|
||||||
error("script_lookup_export(): script.%03d (0x%x) is invalid or not loaded",
|
|
||||||
script_nr, script_nr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
script = script_locate_by_segment(s, seg);
|
|
||||||
|
|
||||||
#ifndef DISABLE_VALIDATIONS
|
|
||||||
if (script && export_index < script->exports_nr && export_index >= 0)
|
|
||||||
#endif
|
|
||||||
return make_reg(seg, READ_LE_UINT16((byte *)(script->export_table + export_index)));
|
return make_reg(seg, READ_LE_UINT16((byte *)(script->export_table + export_index)));
|
||||||
#ifndef DISABLE_VALIDATIONS
|
|
||||||
else {
|
|
||||||
if (!script)
|
|
||||||
error("script_lookup_export(): script.%03d missing", script_nr);
|
|
||||||
else
|
|
||||||
error("script_lookup_export(): script.%03d: Sought invalid export %d/%d",
|
|
||||||
script_nr, export_index, script->exports_nr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : get_class_address(s, id, SCRIPT_GET_LOCK, reg))
|
#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segManager->get_class_address(id, SCRIPT_GET_LOCK, reg))
|
||||||
|
|
||||||
int script_instantiate_common(EngineState *s, int script_nr, Resource **script, Resource **heap, int *was_new) {
|
int script_instantiate_common(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr, Resource **script, Resource **heap, int *was_new) {
|
||||||
int seg_id;
|
int seg_id;
|
||||||
reg_t reg;
|
reg_t reg;
|
||||||
|
|
||||||
*was_new = 1;
|
*was_new = 1;
|
||||||
|
|
||||||
*script = s->resmgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
|
*script = resMgr->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
|
||||||
if (s->_version >= SCI_VERSION_1_1)
|
if (version >= SCI_VERSION_1_1)
|
||||||
*heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
|
*heap = resMgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
|
||||||
|
|
||||||
if (!*script || (s->_version >= SCI_VERSION_1_1 && !heap)) {
|
if (!*script || (version >= SCI_VERSION_1_1 && !heap)) {
|
||||||
warning("Script 0x%x requested but not found", script_nr);
|
warning("Script 0x%x requested but not found", script_nr);
|
||||||
if (s->_version >= SCI_VERSION_1_1) {
|
if (version >= SCI_VERSION_1_1) {
|
||||||
if (*heap)
|
if (*heap)
|
||||||
warning("Inconsistency: heap resource WAS found");
|
warning("Inconsistency: heap resource WAS found");
|
||||||
else if (*script)
|
else if (*script)
|
||||||
|
@ -1607,13 +1540,8 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL == s) {
|
seg_id = segManager->segGet(script_nr);
|
||||||
warning("script_instantiate_common(): script_instantiate(): NULL passed for \"s\"");
|
Script *scr = segManager->getScriptIfLoaded(seg_id);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
seg_id = s->seg_manager->segGet(script_nr);
|
|
||||||
Script *scr = script_locate_by_segment(s, seg_id);
|
|
||||||
if (scr) {
|
if (scr) {
|
||||||
if (!scr->isMarkedAsDeleted()) {
|
if (!scr->isMarkedAsDeleted()) {
|
||||||
scr->incrementLockers();
|
scr->incrementLockers();
|
||||||
|
@ -1622,14 +1550,14 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script,
|
||||||
scr->freeScript();
|
scr->freeScript();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scr = s->seg_manager->allocateScript(s, script_nr, &seg_id);
|
scr = segManager->allocateScript(script_nr, &seg_id);
|
||||||
if (!scr) { // ALL YOUR SCRIPT BASE ARE BELONG TO US
|
if (!scr) { // ALL YOUR SCRIPT BASE ARE BELONG TO US
|
||||||
error("Not enough heap space for script size 0x%x of script 0x%x (Should this happen?)", (*script)->size, script_nr);
|
error("Not enough heap space for script size 0x%x of script 0x%x (Should this happen?)", (*script)->size, script_nr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s->seg_manager->initialiseScript(*scr, s, script_nr);
|
segManager->initialiseScript(*scr, script_nr);
|
||||||
|
|
||||||
reg.segment = seg_id;
|
reg.segment = seg_id;
|
||||||
reg.offset = 0;
|
reg.offset = 0;
|
||||||
|
@ -1645,7 +1573,7 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script,
|
||||||
return seg_id;
|
return seg_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int script_instantiate_sci0(EngineState *s, int script_nr) {
|
int script_instantiate_sci0(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) {
|
||||||
int objtype;
|
int objtype;
|
||||||
unsigned int objlength;
|
unsigned int objlength;
|
||||||
reg_t reg;
|
reg_t reg;
|
||||||
|
@ -1655,7 +1583,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
|
||||||
Resource *script;
|
Resource *script;
|
||||||
int was_new;
|
int was_new;
|
||||||
|
|
||||||
seg_id = script_instantiate_common(s, script_nr, &script, NULL, &was_new);
|
seg_id = script_instantiate_common(resMgr, segManager, version, script_nr, &script, NULL, &was_new);
|
||||||
|
|
||||||
if (was_new)
|
if (was_new)
|
||||||
return seg_id;
|
return seg_id;
|
||||||
|
@ -1663,7 +1591,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
|
||||||
reg.segment = seg_id;
|
reg.segment = seg_id;
|
||||||
reg.offset = 0;
|
reg.offset = 0;
|
||||||
|
|
||||||
Script *scr = s->seg_manager->getScript(seg_id);
|
Script *scr = segManager->getScript(seg_id);
|
||||||
|
|
||||||
if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) {
|
if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) {
|
||||||
//
|
//
|
||||||
|
@ -1678,7 +1606,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
|
||||||
magic_pos_adder = 2; // Step over the funny prefix
|
magic_pos_adder = 2; // Step over the funny prefix
|
||||||
|
|
||||||
if (locals_nr)
|
if (locals_nr)
|
||||||
s->seg_manager->scriptInitialiseLocalsZero(reg.segment, locals_nr);
|
segManager->scriptInitialiseLocalsZero(reg.segment, locals_nr);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
scr->mcpyInOut(0, script->data, script->size);
|
scr->mcpyInOut(0, script->data, script->size);
|
||||||
|
@ -1717,24 +1645,24 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCI_OBJ_LOCALVARS:
|
case SCI_OBJ_LOCALVARS:
|
||||||
s->seg_manager->scriptInitialiseLocals(data_base);
|
segManager->scriptInitialiseLocals(data_base);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCI_OBJ_CLASS: {
|
case SCI_OBJ_CLASS: {
|
||||||
int classpos = addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET;
|
int classpos = addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET;
|
||||||
int species;
|
int species;
|
||||||
species = scr->getHeap(addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET);
|
species = scr->getHeap(addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET);
|
||||||
if (species < 0 || species >= (int)s->_classtable.size()) {
|
if (species < 0 || species >= (int)segManager->_classtable.size()) {
|
||||||
error("Invalid species %d(0x%x) not in interval "
|
error("Invalid species %d(0x%x) not in interval "
|
||||||
"[0,%d) while instantiating script %d\n",
|
"[0,%d) while instantiating script %d\n",
|
||||||
species, species, s->_classtable.size(),
|
species, species, segManager->_classtable.size(),
|
||||||
script_nr);
|
script_nr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->_classtable[species].script = script_nr;
|
segManager->_classtable[species].script = script_nr;
|
||||||
s->_classtable[species].reg = addr;
|
segManager->_classtable[species].reg = addr;
|
||||||
s->_classtable[species].reg.offset = classpos;
|
segManager->_classtable[species].reg.offset = classpos;
|
||||||
// Set technical class position-- into the block allocated for it
|
// Set technical class position-- into the block allocated for it
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1760,17 +1688,17 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
|
||||||
|
|
||||||
switch (objtype) {
|
switch (objtype) {
|
||||||
case SCI_OBJ_CODE:
|
case SCI_OBJ_CODE:
|
||||||
s->seg_manager->scriptAddCodeBlock(addr);
|
segManager->scriptAddCodeBlock(addr);
|
||||||
break;
|
break;
|
||||||
case SCI_OBJ_OBJECT:
|
case SCI_OBJ_OBJECT:
|
||||||
case SCI_OBJ_CLASS: { // object or class?
|
case SCI_OBJ_CLASS: { // object or class?
|
||||||
Object *obj = s->seg_manager->scriptObjInit(s, addr);
|
Object *obj = segManager->scriptObjInit(addr);
|
||||||
Object *base_obj;
|
Object *base_obj;
|
||||||
|
|
||||||
// Instantiate the superclass, if neccessary
|
// Instantiate the superclass, if neccessary
|
||||||
obj->_variables[SCRIPT_SPECIES_SELECTOR] = INST_LOOKUP_CLASS(obj->_variables[SCRIPT_SPECIES_SELECTOR].offset);
|
obj->_variables[SCRIPT_SPECIES_SELECTOR] = INST_LOOKUP_CLASS(obj->_variables[SCRIPT_SPECIES_SELECTOR].offset);
|
||||||
|
|
||||||
base_obj = obj_get(s, obj->_variables[SCRIPT_SPECIES_SELECTOR]);
|
base_obj = obj_get(segManager, version, obj->_variables[SCRIPT_SPECIES_SELECTOR]);
|
||||||
obj->variable_names_nr = base_obj->_variables.size();
|
obj->variable_names_nr = base_obj->_variables.size();
|
||||||
obj->base_obj = base_obj->base_obj;
|
obj->base_obj = base_obj->base_obj;
|
||||||
// Copy base from species class, as we need its selector IDs
|
// Copy base from species class, as we need its selector IDs
|
||||||
|
@ -1791,24 +1719,24 @@ int script_instantiate_sci0(EngineState *s, int script_nr) {
|
||||||
} while ((objtype != 0) && (((unsigned)reg.offset) < script->size - 2));
|
} while ((objtype != 0) && (((unsigned)reg.offset) < script->size - 2));
|
||||||
|
|
||||||
if (relocation >= 0)
|
if (relocation >= 0)
|
||||||
s->seg_manager->scriptRelocate(make_reg(reg.segment, relocation));
|
segManager->scriptRelocate(make_reg(reg.segment, relocation));
|
||||||
|
|
||||||
return reg.segment; // instantiation successful
|
return reg.segment; // instantiation successful
|
||||||
}
|
}
|
||||||
|
|
||||||
int script_instantiate_sci11(EngineState *s, int script_nr) {
|
int script_instantiate_sci11(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) {
|
||||||
Resource *script, *heap;
|
Resource *script, *heap;
|
||||||
int seg_id;
|
int seg_id;
|
||||||
int heap_start;
|
int heap_start;
|
||||||
reg_t reg;
|
reg_t reg;
|
||||||
int was_new;
|
int was_new;
|
||||||
|
|
||||||
seg_id = script_instantiate_common(s, script_nr, &script, &heap, &was_new);
|
seg_id = script_instantiate_common(resMgr, segManager, version, script_nr, &script, &heap, &was_new);
|
||||||
|
|
||||||
if (was_new)
|
if (was_new)
|
||||||
return seg_id;
|
return seg_id;
|
||||||
|
|
||||||
Script *scr = s->seg_manager->getScript(seg_id);
|
Script *scr = segManager->getScript(seg_id);
|
||||||
|
|
||||||
heap_start = script->size;
|
heap_start = script->size;
|
||||||
if (script->size & 2)
|
if (script->size & 2)
|
||||||
|
@ -1822,28 +1750,28 @@ int script_instantiate_sci11(EngineState *s, int script_nr) {
|
||||||
|
|
||||||
reg.segment = seg_id;
|
reg.segment = seg_id;
|
||||||
reg.offset = heap_start + 4;
|
reg.offset = heap_start + 4;
|
||||||
s->seg_manager->scriptInitialiseLocals(reg);
|
segManager->scriptInitialiseLocals(reg);
|
||||||
|
|
||||||
s->seg_manager->scriptRelocateExportsSci11(seg_id);
|
segManager->scriptRelocateExportsSci11(seg_id);
|
||||||
s->seg_manager->scriptInitialiseObjectsSci11(s, seg_id);
|
segManager->scriptInitialiseObjectsSci11(seg_id);
|
||||||
|
|
||||||
reg.offset = READ_LE_UINT16(heap->data);
|
reg.offset = READ_LE_UINT16(heap->data);
|
||||||
s->seg_manager->heapRelocate(reg);
|
segManager->heapRelocate(reg);
|
||||||
|
|
||||||
return seg_id;
|
return seg_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int script_instantiate(EngineState *s, int script_nr) {
|
int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr) {
|
||||||
if (s->_version >= SCI_VERSION_1_1)
|
if (version >= SCI_VERSION_1_1)
|
||||||
return script_instantiate_sci11(s, script_nr);
|
return script_instantiate_sci11(resMgr, segManager, version, script_nr);
|
||||||
else
|
else
|
||||||
return script_instantiate_sci0(s, script_nr);
|
return script_instantiate_sci0(resMgr, segManager, version, script_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) {
|
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);
|
reg_t reg = make_reg(seg, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader() ? 2 : 0);
|
||||||
int objtype, objlength;
|
int objtype, objlength;
|
||||||
Script *scr = s->seg_manager->getScript(seg);
|
Script *scr = segManager->getScript(seg);
|
||||||
|
|
||||||
// Make a pass over the object in order uninstantiate all superclasses
|
// Make a pass over the object in order uninstantiate all superclasses
|
||||||
objlength = 0;
|
objlength = 0;
|
||||||
|
@ -1866,13 +1794,13 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) {
|
||||||
superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
|
superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
|
||||||
|
|
||||||
if (superclass >= 0) {
|
if (superclass >= 0) {
|
||||||
int superclass_script = s->_classtable[superclass].script;
|
int superclass_script = segManager->_classtable[superclass].script;
|
||||||
|
|
||||||
if (superclass_script == script_nr) {
|
if (superclass_script == script_nr) {
|
||||||
if (scr->getLockers())
|
if (scr->getLockers())
|
||||||
scr->decrementLockers(); // Decrease lockers if this is us ourselves
|
scr->decrementLockers(); // Decrease lockers if this is us ourselves
|
||||||
} else
|
} else
|
||||||
script_uninstantiate(s, superclass_script);
|
script_uninstantiate(segManager, version, superclass_script);
|
||||||
// Recurse to assure that the superclass lockers number gets decreased
|
// Recurse to assure that the superclass lockers number gets decreased
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1884,11 +1812,9 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) {
|
||||||
} while (objtype != 0);
|
} while (objtype != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void script_uninstantiate(EngineState *s, int script_nr) {
|
void script_uninstantiate(SegManager *segManager, SciVersion version, int script_nr) {
|
||||||
reg_t reg = make_reg(0, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader() ? 2 : 0);
|
SegmentId segment = segManager->segGet(script_nr);
|
||||||
|
Script *scr = segManager->getScriptIfLoaded(segment);
|
||||||
reg.segment = s->seg_manager->segGet(script_nr);
|
|
||||||
Script *scr = script_locate_by_segment(s, reg.segment);
|
|
||||||
|
|
||||||
if (!scr) { // Is it already loaded?
|
if (!scr) { // Is it already loaded?
|
||||||
//warning("unloading script 0x%x requested although not loaded", script_nr);
|
//warning("unloading script 0x%x requested although not loaded", script_nr);
|
||||||
|
@ -1902,12 +1828,12 @@ void script_uninstantiate(EngineState *s, int script_nr) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Free all classtable references to this script
|
// Free all classtable references to this script
|
||||||
for (uint i = 0; i < s->_classtable.size(); i++)
|
for (uint i = 0; i < segManager->_classtable.size(); i++)
|
||||||
if (s->_classtable[i].reg.segment == reg.segment)
|
if (segManager->_classtable[i].reg.segment == segment)
|
||||||
s->_classtable[i].reg = NULL_REG;
|
segManager->_classtable[i].reg = NULL_REG;
|
||||||
|
|
||||||
if (s->_version < SCI_VERSION_1_1)
|
if (version < SCI_VERSION_1_1)
|
||||||
script_uninstantiate_sci0(s, script_nr, reg.segment);
|
script_uninstantiate_sci0(segManager, version, script_nr, segment);
|
||||||
else
|
else
|
||||||
warning("FIXME: Add proper script uninstantiation for SCI 1.1");
|
warning("FIXME: Add proper script uninstantiation for SCI 1.1");
|
||||||
|
|
||||||
|
@ -1999,8 +1925,8 @@ int game_run(EngineState **_s) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *obj_get(EngineState *s, reg_t offset) {
|
Object *obj_get(SegManager *segManager, SciVersion version, reg_t offset) {
|
||||||
MemObject *mobj = GET_OBJECT_SEGMENT(*s->seg_manager, offset.segment);
|
MemObject *mobj = GET_OBJECT_SEGMENT(*segManager, offset.segment);
|
||||||
Object *obj = NULL;
|
Object *obj = NULL;
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
|
@ -2023,8 +1949,8 @@ Object *obj_get(EngineState *s, reg_t offset) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *obj_get_name(EngineState *s, reg_t pos) {
|
const char *obj_get_name(SegManager *segManager, SciVersion version, reg_t pos) {
|
||||||
Object *obj = obj_get(s, pos);
|
Object *obj = obj_get(segManager, version, pos);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return "<no such object>";
|
return "<no such object>";
|
||||||
|
|
||||||
|
@ -2032,7 +1958,7 @@ const char *obj_get_name(EngineState *s, reg_t pos) {
|
||||||
if (nameReg.isNull())
|
if (nameReg.isNull())
|
||||||
return "<no name>";
|
return "<no name>";
|
||||||
|
|
||||||
const char *name = (const char*)s->seg_manager->dereference(obj->_variables[SCRIPT_NAME_SELECTOR], NULL);
|
const char *name = (const char*)segManager->dereference(obj->_variables[SCRIPT_NAME_SELECTOR], NULL);
|
||||||
if (!name)
|
if (!name)
|
||||||
return "<invalid name>";
|
return "<invalid name>";
|
||||||
|
|
||||||
|
@ -2056,7 +1982,7 @@ void shrink_execution_stack(EngineState *s, uint size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_t* ObjVarRef::getPointer(EngineState *s) const {
|
reg_t* ObjVarRef::getPointer(EngineState *s) const {
|
||||||
Object *o = obj_get(s, obj);
|
Object *o = obj_get(s->seg_manager, s->_version, obj);
|
||||||
if (!o) return 0;
|
if (!o) return 0;
|
||||||
return &(o->_variables[varindex]);
|
return &(o->_variables[varindex]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
/* VM and kernel declarations */
|
/* VM and kernel declarations */
|
||||||
|
|
||||||
#include "sci/engine/vm_types.h" // for reg_t
|
#include "sci/engine/vm_types.h" // for reg_t
|
||||||
|
#include "sci/resource.h" // for SciVersion
|
||||||
|
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
|
@ -39,6 +40,8 @@ struct EngineState;
|
||||||
typedef int sci_version_t;
|
typedef int sci_version_t;
|
||||||
struct IntMapper;
|
struct IntMapper;
|
||||||
struct Object;
|
struct Object;
|
||||||
|
class ResourceManager;
|
||||||
|
extern enum SciVersion;
|
||||||
|
|
||||||
/** Number of bytes to be allocated for the stack */
|
/** Number of bytes to be allocated for the stack */
|
||||||
#define VM_STACK_SIZE 0x1000
|
#define VM_STACK_SIZE 0x1000
|
||||||
|
@ -67,12 +70,12 @@ struct Object;
|
||||||
#define SCRIPT_FUNCTAREAPTR_MAGIC 8 -8
|
#define SCRIPT_FUNCTAREAPTR_MAGIC 8 -8
|
||||||
|
|
||||||
/** Offset of the name pointer */
|
/** Offset of the name pointer */
|
||||||
#define SCRIPT_NAME_OFFSET (s->_version < SCI_VERSION_1_1 ? 14 -8 : 16)
|
#define SCRIPT_NAME_OFFSET (version < SCI_VERSION_1_1 ? 14 -8 : 16)
|
||||||
#define SCRIPT_NAME_SELECTOR (s->_version < SCI_VERSION_1_1 ? 3 : 8)
|
#define SCRIPT_NAME_SELECTOR (version < SCI_VERSION_1_1 ? 3 : 8)
|
||||||
|
|
||||||
/** Object-relative offset of the -info- selector */
|
/** Object-relative offset of the -info- selector */
|
||||||
#define SCRIPT_INFO_OFFSET (s->_version < SCI_VERSION_1_1 ? 12 -8 : 14)
|
#define SCRIPT_INFO_OFFSET (version < SCI_VERSION_1_1 ? 12 -8 : 14)
|
||||||
#define SCRIPT_INFO_SELECTOR (s->_version < SCI_VERSION_1_1 ? 2 : 7)
|
#define SCRIPT_INFO_SELECTOR (version < SCI_VERSION_1_1 ? 2 : 7)
|
||||||
|
|
||||||
/** Flag fo the -info- selector */
|
/** Flag fo the -info- selector */
|
||||||
#define SCRIPT_INFO_CLONE 0x0001
|
#define SCRIPT_INFO_CLONE 0x0001
|
||||||
|
@ -84,18 +87,18 @@ struct Object;
|
||||||
/** Magical object identifier */
|
/** Magical object identifier */
|
||||||
#define SCRIPT_OBJECT_MAGIC_NUMBER 0x1234
|
#define SCRIPT_OBJECT_MAGIC_NUMBER 0x1234
|
||||||
/** Offset of this identifier */
|
/** Offset of this identifier */
|
||||||
#define SCRIPT_OBJECT_MAGIC_OFFSET (s->_version < SCI_VERSION_1_1 ? -8 : 0)
|
#define SCRIPT_OBJECT_MAGIC_OFFSET (version < SCI_VERSION_1_1 ? -8 : 0)
|
||||||
|
|
||||||
/** Script-relative offset of the species ID */
|
/** Script-relative offset of the species ID */
|
||||||
#define SCRIPT_SPECIES_OFFSET 8 -8
|
#define SCRIPT_SPECIES_OFFSET 8 -8
|
||||||
|
|
||||||
#define SCRIPT_SUPERCLASS_OFFSET (s->_version < SCI_VERSION_1_1 ? 10 -8 : 12)
|
#define SCRIPT_SUPERCLASS_OFFSET (version < SCI_VERSION_1_1 ? 10 -8 : 12)
|
||||||
|
|
||||||
/*---------------------------------*/
|
/*---------------------------------*/
|
||||||
/* Script selector index variables */
|
/* Script selector index variables */
|
||||||
/*---------------------------------*/
|
/*---------------------------------*/
|
||||||
#define SCRIPT_SPECIES_SELECTOR (s->_version < SCI_VERSION_1_1 ? 0 : 5)
|
#define SCRIPT_SPECIES_SELECTOR (version < SCI_VERSION_1_1 ? 0 : 5)
|
||||||
#define SCRIPT_SUPERCLASS_SELECTOR (s->_version < SCI_VERSION_1_1 ? 1 : 6)
|
#define SCRIPT_SUPERCLASS_SELECTOR (version < SCI_VERSION_1_1 ? 1 : 6)
|
||||||
#define SCRIPT_CLASSSCRIPT_SELECTOR 4
|
#define SCRIPT_CLASSSCRIPT_SELECTOR 4
|
||||||
|
|
||||||
/** Magic adjustment value for lofsa and lofss */
|
/** Magic adjustment value for lofsa and lofss */
|
||||||
|
@ -466,32 +469,14 @@ void script_free_vm_memory(EngineState *s);
|
||||||
SelectorType lookup_selector(EngineState *s, reg_t obj, Selector selectorid,
|
SelectorType lookup_selector(EngineState *s, reg_t obj, Selector selectorid,
|
||||||
ObjVarRef *varp, reg_t *fptr);
|
ObjVarRef *varp, reg_t *fptr);
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameters for script_get_segment()
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
SCRIPT_GET_DONT_LOAD = 0, /**< Fail if not loaded */
|
|
||||||
SCRIPT_GET_LOAD = 1, /**< Load, if neccessary */
|
|
||||||
SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */
|
|
||||||
} SCRIPT_GET;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the segment occupied by a certain script
|
|
||||||
* @param[in] s The state to operate on
|
|
||||||
* @param[in] script_id The script in question
|
|
||||||
* @param[in] load One of SCRIPT_GET_*
|
|
||||||
* @return The script's segment, or 0 on failure
|
|
||||||
*/
|
|
||||||
SegmentId script_get_segment(EngineState *s, int script_id, SCRIPT_GET load);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks up an entry of the exports table of a script
|
* Looks up an entry of the exports table of a script
|
||||||
* @param[in] s The state to operate on
|
* @param[in] segManager The segment manager
|
||||||
* @param[in] script_nr The script to look up in
|
* @param[in] script_nr The script to look up in
|
||||||
* @param[out] export_index The index of the export entry to look up
|
* @param[out] export_index The index of the export entry to look up
|
||||||
* @return The handle
|
* @return The handle
|
||||||
*/
|
*/
|
||||||
reg_t script_lookup_export(EngineState *s, int script_nr, int export_index);
|
reg_t script_lookup_export(SegManager *segManager, int script_nr, int export_index);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure that a script and its superclasses get loaded to the heap.
|
* Makes sure that a script and its superclasses get loaded to the heap.
|
||||||
|
@ -499,21 +484,24 @@ reg_t script_lookup_export(EngineState *s, int script_nr, int export_index);
|
||||||
* increased. All scripts containing superclasses of this script are loaded
|
* increased. All scripts containing superclasses of this script are loaded
|
||||||
* recursively as well, unless 'recursive' is set to zero. The
|
* recursively as well, unless 'recursive' is set to zero. The
|
||||||
* complementary function is "script_uninstantiate()" below.
|
* complementary function is "script_uninstantiate()" below.
|
||||||
* @param[in] s The state to operate on
|
* @param[in] resMgr The resource manager
|
||||||
|
* @param[in] segManager The segment manager
|
||||||
|
* @param[in] version The SCI version to use
|
||||||
* @param[in] script_nr The script number to load
|
* @param[in] script_nr The script number to load
|
||||||
* @return The script's segment ID or 0 if out of heap
|
* @return The script's segment ID or 0 if out of heap
|
||||||
*/
|
*/
|
||||||
int script_instantiate(EngineState *s, int script_nr);
|
int script_instantiate(ResourceManager *resMgr, SegManager *segManager, SciVersion version, int script_nr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decreases the numer of lockers of a script and unloads it if that number
|
* Decreases the numer of lockers of a script and unloads it if that number
|
||||||
* reaches zero.
|
* reaches zero.
|
||||||
* This function will recursively unload scripts containing its
|
* This function will recursively unload scripts containing its
|
||||||
* superclasses, if those aren't locked by other scripts as well.
|
* superclasses, if those aren't locked by other scripts as well.
|
||||||
* @param[in] s The state to operate on
|
* @param[in] segManager The segment manager
|
||||||
|
* @param[in] version The SCI version to use
|
||||||
* @param[in] script_nr The script number that is requestet to be unloaded
|
* @param[in] script_nr The script number that is requestet to be unloaded
|
||||||
*/
|
*/
|
||||||
void script_uninstantiate(EngineState *s, int script_nr);
|
void script_uninstantiate(SegManager *segManager, SciVersion version, int script_nr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes an SCI game
|
* Initializes an SCI game
|
||||||
|
@ -613,7 +601,7 @@ int kfree(EngineState *s, reg_t handle);
|
||||||
* in a static buffer and need not be freed (neither may
|
* in a static buffer and need not be freed (neither may
|
||||||
* it be modified).
|
* it be modified).
|
||||||
*/
|
*/
|
||||||
const char *obj_get_name(EngineState *s, reg_t pos);
|
const char *obj_get_name(SegManager *segManager, SciVersion version, reg_t pos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves an object from the specified location
|
* Retrieves an object from the specified location
|
||||||
|
@ -621,7 +609,7 @@ const char *obj_get_name(EngineState *s, reg_t pos);
|
||||||
* @param[in] offset The object's offset
|
* @param[in] offset The object's offset
|
||||||
* @return The object in question, or NULL if there is none
|
* @return The object in question, or NULL if there is none
|
||||||
*/
|
*/
|
||||||
Object *obj_get(EngineState *s, reg_t offset);
|
Object *obj_get(SegManager *segManager, SciVersion version, reg_t offset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shrink execution stack to size.
|
* Shrink execution stack to size.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue