[Scummvm-cvs-logs] SF.net SVN: scummvm:[47823] scummvm/trunk/engines/sci/engine

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Tue Feb 2 23:50:33 CET 2010


Revision: 47823
          http://scummvm.svn.sourceforge.net/scummvm/?rev=47823&view=rev
Author:   fingolfin
Date:     2010-02-02 22:50:32 +0000 (Tue, 02 Feb 2010)

Log Message:
-----------
SCI: Move some code around (no code changes)

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/script.cpp
    scummvm/trunk/engines/sci/engine/scriptdebug.cpp
    scummvm/trunk/engines/sci/engine/selector.cpp
    scummvm/trunk/engines/sci/engine/vm.cpp

Modified: scummvm/trunk/engines/sci/engine/script.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/script.cpp	2010-02-02 22:31:32 UTC (rev 47822)
+++ scummvm/trunk/engines/sci/engine/script.cpp	2010-02-02 22:50:32 UTC (rev 47823)
@@ -91,6 +91,8 @@
 };
 #undef END
 
+// TODO: script_adjust_opcode_formats should probably be part of the
+// constructor (?) of a VirtualMachine or a ScriptManager class.
 void script_adjust_opcode_formats(EngineState *s) {
 	// TODO: Check that this is correct
 	if (s->detectLofsType() != SCI_VERSION_0_EARLY) {
@@ -112,380 +114,354 @@
 #endif
 }
 
-#if 1
+#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segMan->getClassAddress(id, SCRIPT_GET_LOCK, reg))
 
-#define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_)
-#define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_)
+int script_instantiate_common(ResourceManager *resMan, SegManager *segMan, int script_nr, Resource **script, Resource **heap, int *was_new) {
+	*was_new = 1;
 
-#else
+	*script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
+	if (getSciVersion() >= SCI_VERSION_1_1)
+		*heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
 
-// The defines below can be used to construct static selector tables for games which don't have
-// a vocab.997 resource, by dumping the selector table from other similar versions or games
-#define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_); \
-	printf("\t{ \"%s\", %d },\n", #_slc_, _selectorCache._slc_)
+	if (!*script || (getSciVersion() >= SCI_VERSION_1_1 && !heap)) {
+		warning("Script 0x%x requested but not found", script_nr);
+		if (getSciVersion() >= SCI_VERSION_1_1) {
+			if (*heap)
+				warning("Inconsistency: heap resource WAS found");
+			else if (*script)
+				warning("Inconsistency: script resource WAS found");
+		}
+		return 0;
+	}
 
-#define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_); \
-	printf("\t{ \"%s\", %d },\n", _slcstr_, _selectorCache._slc_)
+	SegmentId seg_id = segMan->getScriptSegment(script_nr);
+	Script *scr = segMan->getScriptIfLoaded(seg_id);
+	if (scr) {
+		if (!scr->isMarkedAsDeleted()) {
+			scr->incrementLockers();
+			return seg_id;
+		} else {
+			scr->freeScript();
+		}
+	} else {
+		scr = segMan->allocateScript(script_nr, &seg_id);
+		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);
+			return 0;
+		}
+	}
 
-#endif
+	scr->init(script_nr, resMan);
 
-void Kernel::mapSelectors() {
-	// species
-	// superClass
-	// -info-
-	FIND_SELECTOR(y);
-	FIND_SELECTOR(x);
-	FIND_SELECTOR(view);
-	FIND_SELECTOR(loop);
-	FIND_SELECTOR(cel);
-	FIND_SELECTOR(underBits);
-	FIND_SELECTOR(nsTop);
-	FIND_SELECTOR(nsLeft);
-	FIND_SELECTOR(nsBottom);
-	FIND_SELECTOR(lsTop);
-	FIND_SELECTOR(lsLeft);
-	FIND_SELECTOR(lsBottom);
-	FIND_SELECTOR(lsRight);
-	FIND_SELECTOR(nsRight);
-	FIND_SELECTOR(signal);
-	FIND_SELECTOR(illegalBits);
-	FIND_SELECTOR(brTop);
-	FIND_SELECTOR(brLeft);
-	FIND_SELECTOR(brBottom);
-	FIND_SELECTOR(brRight);
-	// name
-	// key
-	// time
-	FIND_SELECTOR(text);
-	FIND_SELECTOR(elements);
-	// color
-	// back
-	FIND_SELECTOR(mode);
-	// style
-	FIND_SELECTOR(state);
-	FIND_SELECTOR(font);
-	FIND_SELECTOR(type);
-	// window
-	FIND_SELECTOR(cursor);
-	FIND_SELECTOR(max);
-	// mark
-	// who
-	FIND_SELECTOR(message);
-	// edit
-	FIND_SELECTOR(play);
-	FIND_SELECTOR(number);
-	FIND_SELECTOR(handle);	// nodePtr
-	FIND_SELECTOR(client);
-	FIND_SELECTOR(dx);
-	FIND_SELECTOR(dy);
-	FIND_SELECTOR2(b_movCnt, "b-moveCnt");
-	FIND_SELECTOR2(b_i1, "b-i1");
-	FIND_SELECTOR2(b_i2, "b-i2");
-	FIND_SELECTOR2(b_di, "b-di");
-	FIND_SELECTOR2(b_xAxis, "b-xAxis");
-	FIND_SELECTOR2(b_incr, "b-incr");
-	FIND_SELECTOR(xStep);
-	FIND_SELECTOR(yStep);
-	FIND_SELECTOR(moveSpeed);
-	FIND_SELECTOR(canBeHere);	// cantBeHere
-	FIND_SELECTOR(heading);
-	FIND_SELECTOR(mover);
-	FIND_SELECTOR(doit);
-	FIND_SELECTOR(isBlocked);
-	FIND_SELECTOR(looper);
-	FIND_SELECTOR(priority);
-	FIND_SELECTOR(modifiers);
-	FIND_SELECTOR(replay);
-	// setPri
-	// at
-	// next
-	// done
-	// width
-	FIND_SELECTOR(wordFail);
-	FIND_SELECTOR(syntaxFail);
-	// semanticFail
-	// pragmaFail
-	// said
-	FIND_SELECTOR(claimed);
-	// value
-	// save
-	// restore
-	// title
-	// button
-	// icon
-	// draw
-	FIND_SELECTOR2(delete_, "delete");
-	FIND_SELECTOR(z);
-	// -----------------------------
-	FIND_SELECTOR(size);
-	FIND_SELECTOR(moveDone);
-	FIND_SELECTOR(vol);
-	FIND_SELECTOR(pri);
-	FIND_SELECTOR(min);
-	FIND_SELECTOR(sec);
-	FIND_SELECTOR(frame);
-	FIND_SELECTOR(dataInc);
-	FIND_SELECTOR(palette);
-	FIND_SELECTOR(cantBeHere);
-	FIND_SELECTOR(nodePtr);
-	FIND_SELECTOR(flags);
-	FIND_SELECTOR(points);
-	FIND_SELECTOR(syncCue);
-	FIND_SELECTOR(syncTime);
-	FIND_SELECTOR(printLang);
-	FIND_SELECTOR(subtitleLang);
-	FIND_SELECTOR(parseLang);
-	FIND_SELECTOR(overlay);
-	FIND_SELECTOR(setCursor);
-	FIND_SELECTOR(topString);
-	FIND_SELECTOR(scaleSignal);
-	FIND_SELECTOR(scaleX);
-	FIND_SELECTOR(scaleY);
+	reg_t reg;
+	reg.segment = seg_id;
+	reg.offset = 0;
 
-#ifdef ENABLE_SCI32
-	FIND_SELECTOR(data);
-	FIND_SELECTOR(picture);
-	FIND_SELECTOR(plane);
-	FIND_SELECTOR(top);
-	FIND_SELECTOR(left);
-#endif
+	// Set heap position (beyond the size word)
+	scr->setLockers(1);
+	scr->setExportTableOffset(0);
+	scr->setSynonymsOffset(0);
+	scr->setSynonymsNr(0);
+
+	*was_new = 0;
+
+	return seg_id;
 }
 
-void Kernel::dumpScriptObject(char *data, int seeker, int objsize) {
-	int selectors, overloads, selectorsize;
-	int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker);
-	int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker);
-	int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker);
-	int i = 0;
+int script_instantiate_sci0(ResourceManager *resMan, SegManager *segMan, int script_nr) {
+	int objtype;
+	unsigned int objlength;
+	int relocation = -1;
+	int magic_pos_adder; // Usually 0; 2 for older SCI versions
+	Resource *script;
+	int was_new;
+	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
 
-	printf("Object\n");
+	const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, NULL, &was_new);
 
-	Common::hexdump((unsigned char *) data + seeker, objsize - 4, 16, seeker);
-	//-4 because the size includes the two-word header
+	if (was_new)
+		return seg_id;
 
-	printf("Name: %s\n", namepos ? ((char *)(data + namepos)) : "<unknown>");
-	printf("Superclass: %x\n", superclass);
-	printf("Species: %x\n", species);
-	printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *) data + 12 + seeker) & 0xffff);
+	Script *scr = segMan->getScript(seg_id);
 
-	printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *) data + seeker + 4));
-	printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *) data + seeker + 6)));
+	if (oldScriptHeader) {
+		//
+		int locals_nr = READ_LE_UINT16(script->data);
 
-	seeker += 8;
+		// Old script block
+		// There won't be a localvar block in this case
+		// Instead, the script starts with a 16 bit int specifying the
+		// number of locals we need; these are then allocated and zeroed.
 
-	while (selectors--) {
-		printf("  [#%03x] = 0x%x\n", i++, (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff);
-		seeker += 2;
+		scr->mcpyInOut(0, script->data, script->size);
+		magic_pos_adder = 2;  // Step over the funny prefix
+
+		if (locals_nr)
+			segMan->scriptInitialiseLocalsZero(seg_id, locals_nr);
+
+	} else {
+		scr->mcpyInOut(0, script->data, script->size);
+		magic_pos_adder = 0;
 	}
 
-	printf("Overridden functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker));
+	// Now do a first pass through the script objects to find the
+	// export table and local variable block
 
-	seeker += 2;
+	reg_t reg;
+	reg.segment = seg_id;
+	reg.offset = magic_pos_adder;
 
-	if (overloads < 100)
-		while (overloads--) {
-			int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker));
+	objlength = 0;
 
-			printf("  [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>");
-			printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors*2 + 2) & 0xffff);
+	do {
+		reg_t data_base;
+		reg_t addr;
+		reg.offset += objlength; // Step over the last checked object
+		objtype = scr->getHeap(reg.offset);
+		if (!objtype)
+			break;
 
-			seeker += 2;
+		objlength = scr->getHeap(reg.offset + 2);
+
+		// This happens in some demos (e.g. the EcoQuest 1 demo). Not sure what is the
+		// actual cause of it, but the scripts of these demos can't be loaded properly
+		// and we're stuck forever in this loop, as objlength never changes
+		if (!objlength) {
+			warning("script_instantiate_sci0: objlength is 0, unable to parse script");
+			return 0;
 		}
-}
 
-void Kernel::dumpScriptClass(char *data, int seeker, int objsize) {
-	int selectors, overloads, selectorsize;
-	int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker);
-	int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker);
-	int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker);
+		data_base = reg;
+		data_base.offset += 4;
 
-	printf("Class\n");
+		addr = data_base;
 
-	Common::hexdump((unsigned char *) data + seeker, objsize - 4, 16, seeker);
+		switch (objtype) {
+		case SCI_OBJ_EXPORTS: {
+			scr->setExportTableOffset(data_base.offset);
+		}
+		break;
 
-	printf("Name: %s\n", namepos ? ((char *)data + namepos) : "<unknown>");
-	printf("Superclass: %x\n", superclass);
-	printf("Species: %x\n", species);
-	printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *)data + 12 + seeker) & 0xffff);
+		case SCI_OBJ_SYNONYMS:
+			scr->setSynonymsOffset(addr.offset);   // +4 is to step over the header
+			scr->setSynonymsNr((objlength) / 4);
+			break;
 
-	printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + 4));
-	printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *)data + seeker + 6)));
+		case SCI_OBJ_LOCALVARS:
+			segMan->scriptInitialiseLocals(data_base);
+			break;
 
-	seeker += 8;
-	selectorsize <<= 1;
+		case SCI_OBJ_CLASS: {
+			int classpos = addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET;
+			int species;
+			species = scr->getHeap(addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET);
+			if (species < 0 || species >= (int)segMan->_classtable.size()) {
+				if (species == (int)segMan->_classtable.size()) {
+					// Happens in the LSL2 demo
+					warning("Applying workaround for an off-by-one invalid species access");
+					segMan->_classtable.resize(segMan->_classtable.size() + 1);
+				} else {
+					warning("Invalid species %d(0x%x) not in interval "
+							  "[0,%d) while instantiating script %d\n",
+							  species, species, segMan->_classtable.size(),
+							  script_nr);
+					return 0;
+				}
+			}
 
-	while (selectors--) {
-		int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker) + selectorsize);
+			segMan->_classtable[species].reg = addr;
+			segMan->_classtable[species].reg.offset = classpos;
+			// Set technical class position-- into the block allocated for it
+		}
+		break;
 
-		printf("  [%03x] %s = 0x%x\n", 0xffff & selector, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>",
-		          (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff);
+		default:
+			break;
+		}
+	} while (objtype != 0);
 
-		seeker += 2;
-	}
+	// And now a second pass to adjust objects and class pointers, and the general pointers
 
-	seeker += selectorsize;
+	objlength = 0;
+	reg.offset = magic_pos_adder; // Reset counter
 
-	printf("Overloaded functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker));
+	do {
+		reg_t addr;
+		reg.offset += objlength; // Step over the last checked object
+		objtype = scr->getHeap(reg.offset);
+		if (!objtype)
+			break;
 
-	seeker += 2;
+		objlength = scr->getHeap(reg.offset + 2);
 
-	while (overloads--) {
-		int selector = (int16)READ_LE_UINT16((unsigned char *)data + (seeker));
-		fprintf(stderr, "selector=%d; selectorNames.size() =%d\n", selector, _selectorNames.size());
-		printf("  [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ?
-		          _selectorNames[selector].c_str() : "<?>");
-		printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors * 2 + 2) & 0xffff);
+		addr = reg;
+		addr.offset += 4; // Step over header
 
-		seeker += 2;
-	}
-}
+		switch (objtype) {
+		case SCI_OBJ_CODE:
+			scr->scriptAddCodeBlock(addr);
+			break;
+		case SCI_OBJ_OBJECT:
+		case SCI_OBJ_CLASS: { // object or class?
+			Object *obj = scr->scriptObjInit(addr);
 
-void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
-	int objectctr[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	unsigned int _seeker = 0;
-	Resource *script = _resMan->findResource(ResourceId(kResourceTypeScript, scriptNumber), 0);
+			// Instantiate the superclass, if neccessary
+			obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector().offset));
 
-	if (!script) {
-		warning("dissectScript(): Script not found!\n");
-		return;
-	}
+			Object *baseObj = segMan->getObject(obj->getSpeciesSelector());
 
-	while (_seeker < script->size) {
-		int objtype = (int16)READ_LE_UINT16(script->data + _seeker);
-		int objsize;
-		unsigned int seeker = _seeker + 4;
+			if (baseObj) {
+				obj->setVarCount(baseObj->getVarCount());
+				// Copy base from species class, as we need its selector IDs
+				obj->_baseObj = baseObj->_baseObj;
 
-		if (!objtype) {
-			printf("End of script object (#0) encountered.\n");
-			printf("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)",
-			          objectctr[6], objectctr[1], objectctr[7], objectctr[10]);
-			return;
+				obj->setSuperClassSelector(INST_LOOKUP_CLASS(obj->getSuperClassSelector().offset));
+			} else {
+				warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
+
+				scr->scriptObjRemove(addr);
+			}
+		} // if object or class
+		break;
+		case SCI_OBJ_POINTERS: // A relocation table
+			relocation = addr.offset;
+			break;
+
+		default:
+			break;
 		}
 
-		printf("\n");
+	} while (objtype != 0 && reg.offset < script->size - 2);
 
-		objsize = (int16)READ_LE_UINT16(script->data + _seeker + 2);
+	if (relocation >= 0)
+		scr->scriptRelocate(make_reg(seg_id, relocation));
 
-		printf("Obj type #%x, size 0x%x: ", objtype, objsize);
+	return reg.segment;		// instantiation successful
+}
 
-		_seeker += objsize;
+int script_instantiate_sci11(ResourceManager *resMan, SegManager *segMan, int script_nr) {
+	Resource *script, *heap;
+	int _heapStart;
+	reg_t reg;
+	int was_new;
 
-		objectctr[objtype]++;
+	const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, &heap, &was_new);
 
-		switch (objtype) {
-		case SCI_OBJ_OBJECT:
-			dumpScriptObject((char *)script->data, seeker, objsize);
-			break;
+	if (was_new)
+		return seg_id;
 
-		case SCI_OBJ_CODE: {
-			printf("Code\n");
-			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
-		};
-		break;
+	Script *scr = segMan->getScript(seg_id);
 
-		case 3: {
-			printf("<unknown>\n");
-			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
-		};
-		break;
+	_heapStart = script->size;
+	if (script->size & 2)
+		_heapStart ++;
 
-		case SCI_OBJ_SAID: {
-			printf("Said\n");
-			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
+	scr->mcpyInOut(0, script->data, script->size);
+	scr->mcpyInOut(_heapStart, heap->data, heap->size);
 
-			printf("%04x: ", seeker);
-			while (seeker < _seeker) {
-				unsigned char nextitem = script->data [seeker++];
-				if (nextitem == 0xFF)
-					printf("\n%04x: ", seeker);
-				else if (nextitem >= 0xF0) {
-					switch (nextitem) {
-					case 0xf0:
-						printf(", ");
-						break;
-					case 0xf1:
-						printf("& ");
-						break;
-					case 0xf2:
-						printf("/ ");
-						break;
-					case 0xf3:
-						printf("( ");
-						break;
-					case 0xf4:
-						printf(") ");
-						break;
-					case 0xf5:
-						printf("[ ");
-						break;
-					case 0xf6:
-						printf("] ");
-						break;
-					case 0xf7:
-						printf("# ");
-						break;
-					case 0xf8:
-						printf("< ");
-						break;
-					case 0xf9:
-						printf("> ");
-						break;
-					}
-				} else {
-					nextitem = nextitem << 8 | script->data [seeker++];
-					printf("%s[%03x] ", vocab->getAnyWordFromGroup(nextitem), nextitem);
-				}
-			}
-			printf("\n");
-		}
-		break;
+	if (READ_LE_UINT16(script->data + 6) > 0)
+		scr->setExportTableOffset(6);
 
-		case SCI_OBJ_STRINGS: {
-			printf("Strings\n");
-			while (script->data [seeker]) {
-				printf("%04x: %s\n", seeker, script->data + seeker);
-				seeker += strlen((char *)script->data + seeker) + 1;
-			}
-			seeker++; // the ending zero byte
-		};
-		break;
+	reg.segment = seg_id;
+	reg.offset = _heapStart + 4;
+	segMan->scriptInitialiseLocals(reg);
 
-		case SCI_OBJ_CLASS:
-			dumpScriptClass((char *)script->data, seeker, objsize);
+	segMan->scriptRelocateExportsSci11(seg_id);
+	segMan->scriptInitialiseObjectsSci11(seg_id);
+
+	reg.offset = READ_LE_UINT16(heap->data);
+	scr->heapRelocate(reg);
+
+	return seg_id;
+}
+
+int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr) {
+	if (getSciVersion() >= SCI_VERSION_1_1)
+		return script_instantiate_sci11(resMan, segMan, script_nr);
+	else
+		return script_instantiate_sci0(resMan, segMan, script_nr);
+}
+
+void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) {
+	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+	reg_t reg = make_reg(seg, oldScriptHeader ? 2 : 0);
+	int objtype, objlength;
+	Script *scr = segMan->getScript(seg);
+
+	// Make a pass over the object in order uninstantiate all superclasses
+	objlength = 0;
+
+	do {
+		reg.offset += objlength; // Step over the last checked object
+
+		objtype = scr->getHeap(reg.offset);
+		if (!objtype)
 			break;
+		objlength = scr->getHeap(reg.offset + 2);  // use SEG_UGET_HEAP ??
 
-		case SCI_OBJ_EXPORTS: {
-			printf("Exports\n");
-			Common::hexdump((unsigned char *)script->data + seeker, objsize - 4, 16, seeker);
-		};
-		break;
+		reg.offset += 4; // Step over header
 
-		case SCI_OBJ_POINTERS: {
-			printf("Pointers\n");
-			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
-		};
-		break;
+		if ((objtype == SCI_OBJ_OBJECT) || (objtype == SCI_OBJ_CLASS)) { // object or class?
+			int superclass;
 
-		case 9: {
-			printf("<unknown>\n");
-			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
-		};
-		break;
+			reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET;
 
-		case SCI_OBJ_LOCALVARS: {
-			printf("Local vars\n");
-			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
-		};
-		break;
+			superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
 
-		default:
-			printf("Unsupported!\n");
-			return;
-		}
+			if (superclass >= 0) {
+				int superclass_script = segMan->_classtable[superclass].script;
 
+				if (superclass_script == script_nr) {
+					if (scr->getLockers())
+						scr->decrementLockers();  // Decrease lockers if this is us ourselves
+				} else
+					script_uninstantiate(segMan, superclass_script);
+				// Recurse to assure that the superclass lockers number gets decreased
+			}
+
+			reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET;
+		} // if object or class
+
+		reg.offset -= 4; // Step back on header
+
+	} while (objtype != 0);
+}
+
+void script_uninstantiate(SegManager *segMan, int script_nr) {
+	SegmentId segment = segMan->getScriptSegment(script_nr);
+	Script *scr = segMan->getScriptIfLoaded(segment);
+
+	if (!scr) {   // Is it already loaded?
+		//warning("unloading script 0x%x requested although not loaded", script_nr);
+		// This is perfectly valid SCI behaviour
+		return;
 	}
 
-	printf("Script ends without terminator\n");
+	scr->decrementLockers();   // One less locker
+
+	if (scr->getLockers() > 0)
+		return;
+
+	// Free all classtable references to this script
+	for (uint i = 0; i < segMan->_classtable.size(); i++)
+		if (segMan->_classtable[i].reg.segment == segment)
+			segMan->_classtable[i].reg = NULL_REG;
+
+	if (getSciVersion() < SCI_VERSION_1_1)
+		script_uninstantiate_sci0(segMan, script_nr, segment);
+	// FIXME: Add proper script uninstantiation for SCI 1.1
+
+	if (scr->getLockers())
+		return; // if xxx.lockers > 0
+
+	// Otherwise unload it completely
+	// Explanation: I'm starting to believe that this work is done by SCI itself.
+	scr->markDeleted();
+
+	debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
+
+	return;
 }
 
+
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/engine/scriptdebug.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/scriptdebug.cpp	2010-02-02 22:31:32 UTC (rev 47822)
+++ scummvm/trunk/engines/sci/engine/scriptdebug.cpp	2010-02-02 22:50:32 UTC (rev 47823)
@@ -428,4 +428,241 @@
 	con->attach();
 }
 
+void Kernel::dumpScriptObject(char *data, int seeker, int objsize) {
+	int selectors, overloads, selectorsize;
+	int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker);
+	int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker);
+	int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker);
+	int i = 0;
+
+	printf("Object\n");
+
+	Common::hexdump((unsigned char *) data + seeker, objsize - 4, 16, seeker);
+	//-4 because the size includes the two-word header
+
+	printf("Name: %s\n", namepos ? ((char *)(data + namepos)) : "<unknown>");
+	printf("Superclass: %x\n", superclass);
+	printf("Species: %x\n", species);
+	printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *) data + 12 + seeker) & 0xffff);
+
+	printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *) data + seeker + 4));
+	printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *) data + seeker + 6)));
+
+	seeker += 8;
+
+	while (selectors--) {
+		printf("  [#%03x] = 0x%x\n", i++, (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff);
+		seeker += 2;
+	}
+
+	printf("Overridden functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker));
+
+	seeker += 2;
+
+	if (overloads < 100)
+		while (overloads--) {
+			int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker));
+
+			printf("  [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>");
+			printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors*2 + 2) & 0xffff);
+
+			seeker += 2;
+		}
+}
+
+void Kernel::dumpScriptClass(char *data, int seeker, int objsize) {
+	int selectors, overloads, selectorsize;
+	int species = (int16)READ_LE_UINT16((unsigned char *) data + 8 + seeker);
+	int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker);
+	int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker);
+
+	printf("Class\n");
+
+	Common::hexdump((unsigned char *) data + seeker, objsize - 4, 16, seeker);
+
+	printf("Name: %s\n", namepos ? ((char *)data + namepos) : "<unknown>");
+	printf("Superclass: %x\n", superclass);
+	printf("Species: %x\n", species);
+	printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *)data + 12 + seeker) & 0xffff);
+
+	printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + 4));
+	printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *)data + seeker + 6)));
+
+	seeker += 8;
+	selectorsize <<= 1;
+
+	while (selectors--) {
+		int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker) + selectorsize);
+
+		printf("  [%03x] %s = 0x%x\n", 0xffff & selector, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>",
+		          (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff);
+
+		seeker += 2;
+	}
+
+	seeker += selectorsize;
+
+	printf("Overloaded functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker));
+
+	seeker += 2;
+
+	while (overloads--) {
+		int selector = (int16)READ_LE_UINT16((unsigned char *)data + (seeker));
+		fprintf(stderr, "selector=%d; selectorNames.size() =%d\n", selector, _selectorNames.size());
+		printf("  [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ?
+		          _selectorNames[selector].c_str() : "<?>");
+		printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors * 2 + 2) & 0xffff);
+
+		seeker += 2;
+	}
+}
+
+void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
+	int objectctr[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	unsigned int _seeker = 0;
+	Resource *script = _resMan->findResource(ResourceId(kResourceTypeScript, scriptNumber), 0);
+
+	if (!script) {
+		warning("dissectScript(): Script not found!\n");
+		return;
+	}
+
+	while (_seeker < script->size) {
+		int objtype = (int16)READ_LE_UINT16(script->data + _seeker);
+		int objsize;
+		unsigned int seeker = _seeker + 4;
+
+		if (!objtype) {
+			printf("End of script object (#0) encountered.\n");
+			printf("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)",
+			          objectctr[6], objectctr[1], objectctr[7], objectctr[10]);
+			return;
+		}
+
+		printf("\n");
+
+		objsize = (int16)READ_LE_UINT16(script->data + _seeker + 2);
+
+		printf("Obj type #%x, size 0x%x: ", objtype, objsize);
+
+		_seeker += objsize;
+
+		objectctr[objtype]++;
+
+		switch (objtype) {
+		case SCI_OBJ_OBJECT:
+			dumpScriptObject((char *)script->data, seeker, objsize);
+			break;
+
+		case SCI_OBJ_CODE: {
+			printf("Code\n");
+			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
+		};
+		break;
+
+		case 3: {
+			printf("<unknown>\n");
+			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
+		};
+		break;
+
+		case SCI_OBJ_SAID: {
+			printf("Said\n");
+			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
+
+			printf("%04x: ", seeker);
+			while (seeker < _seeker) {
+				unsigned char nextitem = script->data [seeker++];
+				if (nextitem == 0xFF)
+					printf("\n%04x: ", seeker);
+				else if (nextitem >= 0xF0) {
+					switch (nextitem) {
+					case 0xf0:
+						printf(", ");
+						break;
+					case 0xf1:
+						printf("& ");
+						break;
+					case 0xf2:
+						printf("/ ");
+						break;
+					case 0xf3:
+						printf("( ");
+						break;
+					case 0xf4:
+						printf(") ");
+						break;
+					case 0xf5:
+						printf("[ ");
+						break;
+					case 0xf6:
+						printf("] ");
+						break;
+					case 0xf7:
+						printf("# ");
+						break;
+					case 0xf8:
+						printf("< ");
+						break;
+					case 0xf9:
+						printf("> ");
+						break;
+					}
+				} else {
+					nextitem = nextitem << 8 | script->data [seeker++];
+					printf("%s[%03x] ", vocab->getAnyWordFromGroup(nextitem), nextitem);
+				}
+			}
+			printf("\n");
+		}
+		break;
+
+		case SCI_OBJ_STRINGS: {
+			printf("Strings\n");
+			while (script->data [seeker]) {
+				printf("%04x: %s\n", seeker, script->data + seeker);
+				seeker += strlen((char *)script->data + seeker) + 1;
+			}
+			seeker++; // the ending zero byte
+		};
+		break;
+
+		case SCI_OBJ_CLASS:
+			dumpScriptClass((char *)script->data, seeker, objsize);
+			break;
+
+		case SCI_OBJ_EXPORTS: {
+			printf("Exports\n");
+			Common::hexdump((unsigned char *)script->data + seeker, objsize - 4, 16, seeker);
+		};
+		break;
+
+		case SCI_OBJ_POINTERS: {
+			printf("Pointers\n");
+			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
+		};
+		break;
+
+		case 9: {
+			printf("<unknown>\n");
+			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
+		};
+		break;
+
+		case SCI_OBJ_LOCALVARS: {
+			printf("Local vars\n");
+			Common::hexdump(script->data + seeker, objsize - 4, 16, seeker);
+		};
+		break;
+
+		default:
+			printf("Unsupported!\n");
+			return;
+		}
+
+	}
+
+	printf("Script ends without terminator\n");
+}
+
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/engine/selector.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/selector.cpp	2010-02-02 22:31:32 UTC (rev 47822)
+++ scummvm/trunk/engines/sci/engine/selector.cpp	2010-02-02 22:50:32 UTC (rev 47823)
@@ -29,6 +29,145 @@
 
 namespace Sci {
 
+#if 1
+
+#define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_)
+#define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_)
+
+#else
+
+// The defines below can be used to construct static selector tables for games which don't have
+// a vocab.997 resource, by dumping the selector table from other similar versions or games
+#define FIND_SELECTOR(_slc_) _selectorCache._slc_ = findSelector(#_slc_); \
+	printf("\t{ \"%s\", %d },\n", #_slc_, _selectorCache._slc_)
+
+#define FIND_SELECTOR2(_slc_, _slcstr_) _selectorCache._slc_ = findSelector(_slcstr_); \
+	printf("\t{ \"%s\", %d },\n", _slcstr_, _selectorCache._slc_)
+
+#endif
+
+void Kernel::mapSelectors() {
+	// species
+	// superClass
+	// -info-
+	FIND_SELECTOR(y);
+	FIND_SELECTOR(x);
+	FIND_SELECTOR(view);
+	FIND_SELECTOR(loop);
+	FIND_SELECTOR(cel);
+	FIND_SELECTOR(underBits);
+	FIND_SELECTOR(nsTop);
+	FIND_SELECTOR(nsLeft);
+	FIND_SELECTOR(nsBottom);
+	FIND_SELECTOR(lsTop);
+	FIND_SELECTOR(lsLeft);
+	FIND_SELECTOR(lsBottom);
+	FIND_SELECTOR(lsRight);
+	FIND_SELECTOR(nsRight);
+	FIND_SELECTOR(signal);
+	FIND_SELECTOR(illegalBits);
+	FIND_SELECTOR(brTop);
+	FIND_SELECTOR(brLeft);
+	FIND_SELECTOR(brBottom);
+	FIND_SELECTOR(brRight);
+	// name
+	// key
+	// time
+	FIND_SELECTOR(text);
+	FIND_SELECTOR(elements);
+	// color
+	// back
+	FIND_SELECTOR(mode);
+	// style
+	FIND_SELECTOR(state);
+	FIND_SELECTOR(font);
+	FIND_SELECTOR(type);
+	// window
+	FIND_SELECTOR(cursor);
+	FIND_SELECTOR(max);
+	// mark
+	// who
+	FIND_SELECTOR(message);
+	// edit
+	FIND_SELECTOR(play);
+	FIND_SELECTOR(number);
+	FIND_SELECTOR(handle);	// nodePtr
+	FIND_SELECTOR(client);
+	FIND_SELECTOR(dx);
+	FIND_SELECTOR(dy);
+	FIND_SELECTOR2(b_movCnt, "b-moveCnt");
+	FIND_SELECTOR2(b_i1, "b-i1");
+	FIND_SELECTOR2(b_i2, "b-i2");
+	FIND_SELECTOR2(b_di, "b-di");
+	FIND_SELECTOR2(b_xAxis, "b-xAxis");
+	FIND_SELECTOR2(b_incr, "b-incr");
+	FIND_SELECTOR(xStep);
+	FIND_SELECTOR(yStep);
+	FIND_SELECTOR(moveSpeed);
+	FIND_SELECTOR(canBeHere);	// cantBeHere
+	FIND_SELECTOR(heading);
+	FIND_SELECTOR(mover);
+	FIND_SELECTOR(doit);
+	FIND_SELECTOR(isBlocked);
+	FIND_SELECTOR(looper);
+	FIND_SELECTOR(priority);
+	FIND_SELECTOR(modifiers);
+	FIND_SELECTOR(replay);
+	// setPri
+	// at
+	// next
+	// done
+	// width
+	FIND_SELECTOR(wordFail);
+	FIND_SELECTOR(syntaxFail);
+	// semanticFail
+	// pragmaFail
+	// said
+	FIND_SELECTOR(claimed);
+	// value
+	// save
+	// restore
+	// title
+	// button
+	// icon
+	// draw
+	FIND_SELECTOR2(delete_, "delete");
+	FIND_SELECTOR(z);
+	// -----------------------------
+	FIND_SELECTOR(size);
+	FIND_SELECTOR(moveDone);
+	FIND_SELECTOR(vol);
+	FIND_SELECTOR(pri);
+	FIND_SELECTOR(min);
+	FIND_SELECTOR(sec);
+	FIND_SELECTOR(frame);
+	FIND_SELECTOR(dataInc);
+	FIND_SELECTOR(palette);
+	FIND_SELECTOR(cantBeHere);
+	FIND_SELECTOR(nodePtr);
+	FIND_SELECTOR(flags);
+	FIND_SELECTOR(points);
+	FIND_SELECTOR(syncCue);
+	FIND_SELECTOR(syncTime);
+	FIND_SELECTOR(printLang);
+	FIND_SELECTOR(subtitleLang);
+	FIND_SELECTOR(parseLang);
+	FIND_SELECTOR(overlay);
+	FIND_SELECTOR(setCursor);
+	FIND_SELECTOR(topString);
+	FIND_SELECTOR(scaleSignal);
+	FIND_SELECTOR(scaleX);
+	FIND_SELECTOR(scaleY);
+
+#ifdef ENABLE_SCI32
+	FIND_SELECTOR(data);
+	FIND_SELECTOR(picture);
+	FIND_SELECTOR(plane);
+	FIND_SELECTOR(top);
+	FIND_SELECTOR(left);
+#endif
+}
+
 reg_t read_selector(SegManager *segMan, reg_t object, Selector selector_id) {
 	ObjVarRef address;
 

Modified: scummvm/trunk/engines/sci/engine/vm.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/vm.cpp	2010-02-02 22:31:32 UTC (rev 47822)
+++ scummvm/trunk/engines/sci/engine/vm.cpp	2010-02-02 22:50:32 UTC (rev 47823)
@@ -1603,355 +1603,6 @@
 	}
 }
 
-#define INST_LOOKUP_CLASS(id) ((id == 0xffff)? NULL_REG : segMan->getClassAddress(id, SCRIPT_GET_LOCK, reg))
-
-int script_instantiate_common(ResourceManager *resMan, SegManager *segMan, int script_nr, Resource **script, Resource **heap, int *was_new) {
-	*was_new = 1;
-
-	*script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
-	if (getSciVersion() >= SCI_VERSION_1_1)
-		*heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0);
-
-	if (!*script || (getSciVersion() >= SCI_VERSION_1_1 && !heap)) {
-		warning("Script 0x%x requested but not found", script_nr);
-		if (getSciVersion() >= SCI_VERSION_1_1) {
-			if (*heap)
-				warning("Inconsistency: heap resource WAS found");
-			else if (*script)
-				warning("Inconsistency: script resource WAS found");
-		}
-		return 0;
-	}
-
-	SegmentId seg_id = segMan->getScriptSegment(script_nr);
-	Script *scr = segMan->getScriptIfLoaded(seg_id);
-	if (scr) {
-		if (!scr->isMarkedAsDeleted()) {
-			scr->incrementLockers();
-			return seg_id;
-		} else {
-			scr->freeScript();
-		}
-	} else {
-		scr = segMan->allocateScript(script_nr, &seg_id);
-		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);
-			return 0;
-		}
-	}
-
-	scr->init(script_nr, resMan);
-
-	reg_t reg;
-	reg.segment = seg_id;
-	reg.offset = 0;
-
-	// Set heap position (beyond the size word)
-	scr->setLockers(1);
-	scr->setExportTableOffset(0);
-	scr->setSynonymsOffset(0);
-	scr->setSynonymsNr(0);
-
-	*was_new = 0;
-
-	return seg_id;
-}
-
-int script_instantiate_sci0(ResourceManager *resMan, SegManager *segMan, int script_nr) {
-	int objtype;
-	unsigned int objlength;
-	int relocation = -1;
-	int magic_pos_adder; // Usually 0; 2 for older SCI versions
-	Resource *script;
-	int was_new;
-	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
-
-	const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, NULL, &was_new);
-
-	if (was_new)
-		return seg_id;
-
-	Script *scr = segMan->getScript(seg_id);
-
-	if (oldScriptHeader) {
-		//
-		int locals_nr = READ_LE_UINT16(script->data);
-
-		// Old script block
-		// There won't be a localvar block in this case
-		// Instead, the script starts with a 16 bit int specifying the
-		// number of locals we need; these are then allocated and zeroed.
-
-		scr->mcpyInOut(0, script->data, script->size);
-		magic_pos_adder = 2;  // Step over the funny prefix
-
-		if (locals_nr)
-			segMan->scriptInitialiseLocalsZero(seg_id, locals_nr);
-
-	} else {
-		scr->mcpyInOut(0, script->data, script->size);
-		magic_pos_adder = 0;
-	}
-
-	// Now do a first pass through the script objects to find the
-	// export table and local variable block
-
-	reg_t reg;
-	reg.segment = seg_id;
-	reg.offset = magic_pos_adder;
-
-	objlength = 0;
-
-	do {
-		reg_t data_base;
-		reg_t addr;
-		reg.offset += objlength; // Step over the last checked object
-		objtype = scr->getHeap(reg.offset);
-		if (!objtype)
-			break;
-
-		objlength = scr->getHeap(reg.offset + 2);
-
-		// This happens in some demos (e.g. the EcoQuest 1 demo). Not sure what is the
-		// actual cause of it, but the scripts of these demos can't be loaded properly
-		// and we're stuck forever in this loop, as objlength never changes
-		if (!objlength) {
-			warning("script_instantiate_sci0: objlength is 0, unable to parse script");
-			return 0;
-		}
-
-		data_base = reg;
-		data_base.offset += 4;
-
-		addr = data_base;
-
-		switch (objtype) {
-		case SCI_OBJ_EXPORTS: {
-			scr->setExportTableOffset(data_base.offset);
-		}
-		break;
-
-		case SCI_OBJ_SYNONYMS:
-			scr->setSynonymsOffset(addr.offset);   // +4 is to step over the header
-			scr->setSynonymsNr((objlength) / 4);
-			break;
-
-		case SCI_OBJ_LOCALVARS:
-			segMan->scriptInitialiseLocals(data_base);
-			break;
-
-		case SCI_OBJ_CLASS: {
-			int classpos = addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET;
-			int species;
-			species = scr->getHeap(addr.offset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET);
-			if (species < 0 || species >= (int)segMan->_classtable.size()) {
-				if (species == (int)segMan->_classtable.size()) {
-					// Happens in the LSL2 demo
-					warning("Applying workaround for an off-by-one invalid species access");
-					segMan->_classtable.resize(segMan->_classtable.size() + 1);
-				} else {
-					warning("Invalid species %d(0x%x) not in interval "
-							  "[0,%d) while instantiating script %d\n",
-							  species, species, segMan->_classtable.size(),
-							  script_nr);
-					return 0;
-				}
-			}
-
-			segMan->_classtable[species].reg = addr;
-			segMan->_classtable[species].reg.offset = classpos;
-			// Set technical class position-- into the block allocated for it
-		}
-		break;
-
-		default:
-			break;
-		}
-	} while (objtype != 0);
-
-	// And now a second pass to adjust objects and class pointers, and the general pointers
-
-	objlength = 0;
-	reg.offset = magic_pos_adder; // Reset counter
-
-	do {
-		reg_t addr;
-		reg.offset += objlength; // Step over the last checked object
-		objtype = scr->getHeap(reg.offset);
-		if (!objtype)
-			break;
-
-		objlength = scr->getHeap(reg.offset + 2);
-
-		addr = reg;
-		addr.offset += 4; // Step over header
-
-		switch (objtype) {
-		case SCI_OBJ_CODE:
-			scr->scriptAddCodeBlock(addr);
-			break;
-		case SCI_OBJ_OBJECT:
-		case SCI_OBJ_CLASS: { // object or class?
-			Object *obj = scr->scriptObjInit(addr);
-
-			// Instantiate the superclass, if neccessary
-			obj->setSpeciesSelector(INST_LOOKUP_CLASS(obj->getSpeciesSelector().offset));
-
-			Object *baseObj = segMan->getObject(obj->getSpeciesSelector());
-
-			if (baseObj) {
-				obj->setVarCount(baseObj->getVarCount());
-				// Copy base from species class, as we need its selector IDs
-				obj->_baseObj = baseObj->_baseObj;
-
-				obj->setSuperClassSelector(INST_LOOKUP_CLASS(obj->getSuperClassSelector().offset));
-			} else {
-				warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
-
-				scr->scriptObjRemove(addr);
-			}
-		} // if object or class
-		break;
-		case SCI_OBJ_POINTERS: // A relocation table
-			relocation = addr.offset;
-			break;
-
-		default:
-			break;
-		}
-
-	} while (objtype != 0 && reg.offset < script->size - 2);
-
-	if (relocation >= 0)
-		scr->scriptRelocate(make_reg(seg_id, relocation));
-
-	return reg.segment;		// instantiation successful
-}
-
-int script_instantiate_sci11(ResourceManager *resMan, SegManager *segMan, int script_nr) {
-	Resource *script, *heap;
-	int _heapStart;
-	reg_t reg;
-	int was_new;
-
-	const int seg_id = script_instantiate_common(resMan, segMan, script_nr, &script, &heap, &was_new);
-
-	if (was_new)
-		return seg_id;
-
-	Script *scr = segMan->getScript(seg_id);
-
-	_heapStart = script->size;
-	if (script->size & 2)
-		_heapStart ++;
-
-	scr->mcpyInOut(0, script->data, script->size);
-	scr->mcpyInOut(_heapStart, heap->data, heap->size);
-
-	if (READ_LE_UINT16(script->data + 6) > 0)
-		scr->setExportTableOffset(6);
-
-	reg.segment = seg_id;
-	reg.offset = _heapStart + 4;
-	segMan->scriptInitialiseLocals(reg);
-
-	segMan->scriptRelocateExportsSci11(seg_id);
-	segMan->scriptInitialiseObjectsSci11(seg_id);
-
-	reg.offset = READ_LE_UINT16(heap->data);
-	scr->heapRelocate(reg);
-
-	return seg_id;
-}
-
-int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr) {
-	if (getSciVersion() >= SCI_VERSION_1_1)
-		return script_instantiate_sci11(resMan, segMan, script_nr);
-	else
-		return script_instantiate_sci0(resMan, segMan, script_nr);
-}
-
-void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) {
-	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
-	reg_t reg = make_reg(seg, oldScriptHeader ? 2 : 0);
-	int objtype, objlength;
-	Script *scr = segMan->getScript(seg);
-
-	// Make a pass over the object in order uninstantiate all superclasses
-	objlength = 0;
-
-	do {
-		reg.offset += objlength; // Step over the last checked object
-
-		objtype = scr->getHeap(reg.offset);
-		if (!objtype)
-			break;
-		objlength = scr->getHeap(reg.offset + 2);  // use SEG_UGET_HEAP ??
-
-		reg.offset += 4; // Step over header
-
-		if ((objtype == SCI_OBJ_OBJECT) || (objtype == SCI_OBJ_CLASS)) { // object or class?
-			int superclass;
-
-			reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET;
-
-			superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
-
-			if (superclass >= 0) {
-				int superclass_script = segMan->_classtable[superclass].script;
-
-				if (superclass_script == script_nr) {
-					if (scr->getLockers())
-						scr->decrementLockers();  // Decrease lockers if this is us ourselves
-				} else
-					script_uninstantiate(segMan, superclass_script);
-				// Recurse to assure that the superclass lockers number gets decreased
-			}
-
-			reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET;
-		} // if object or class
-
-		reg.offset -= 4; // Step back on header
-
-	} while (objtype != 0);
-}
-
-void script_uninstantiate(SegManager *segMan, int script_nr) {
-	SegmentId segment = segMan->getScriptSegment(script_nr);
-	Script *scr = segMan->getScriptIfLoaded(segment);
-
-	if (!scr) {   // Is it already loaded?
-		//warning("unloading script 0x%x requested although not loaded", script_nr);
-		// This is perfectly valid SCI behaviour
-		return;
-	}
-
-	scr->decrementLockers();   // One less locker
-
-	if (scr->getLockers() > 0)
-		return;
-
-	// Free all classtable references to this script
-	for (uint i = 0; i < segMan->_classtable.size(); i++)
-		if (segMan->_classtable[i].reg.segment == segment)
-			segMan->_classtable[i].reg = NULL_REG;
-
-	if (getSciVersion() < SCI_VERSION_1_1)
-		script_uninstantiate_sci0(segMan, script_nr, segment);
-	// FIXME: Add proper script uninstantiation for SCI 1.1
-
-	if (scr->getLockers())
-		return; // if xxx.lockers > 0
-
-	// Otherwise unload it completely
-	// Explanation: I'm starting to believe that this work is done by SCI itself.
-	scr->markDeleted();
-
-	debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
-
-	return;
-}
-
 static void _init_stack_base_with_selector(EngineState *s, Selector selector) {
 	s->stack_base[0] = make_reg(0, (uint16)selector);
 	s->stack_base[1] = NULL_REG;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list