Пример #1
0
Common::String Kernel::lookupText(reg_t address, int index) {
	char *seeker;
	Resource *textres;

	if (address.getSegment())
		return _segMan->getString(address);

	int textlen;
	int _index = index;
	textres = _resMan->findResource(ResourceId(kResourceTypeText, address.getOffset()), 0);

	if (!textres) {
		error("text.%03d not found", address.getOffset());
		return NULL; /* Will probably segfault */
	}

	textlen = textres->size;
	seeker = (char *) textres->data;

	while (index--)
		while ((textlen--) && (*seeker++))
			;

	if (textlen)
		return seeker;

	error("Index %d out of bounds in text.%03d", _index, address.getOffset());
	return NULL;
}
Пример #2
0
SegmentRef Script::dereference(reg_t pointer) {
	if (pointer.getOffset() > _buf->size()) {
		error("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script %d segment (script size=%u)",
				  PRINT_REG(pointer), _nr, _buf->size());
		return SegmentRef();
	}

	SegmentRef ret;
	ret.isRaw = true;
	ret.maxSize = _buf->size() - pointer.getOffset();
	ret.raw = _buf->getUnsafeDataAt(pointer.getOffset(), ret.maxSize);
	return ret;
}
Пример #3
0
static void patchGameSaveRestoreCodeSci2(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) {
	Script *script = segMan->getScript(methodAddress.getSegment());
	byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset()));
	int kcallOffset;

	if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) {
		if (doRestore) {
			memcpy(patchPtr, patchGameRestoreSci2, sizeof(patchGameRestoreSci2));
			kcallOffset = 9;
		} else {
			memcpy(patchPtr, patchGameSaveSci2, sizeof(patchGameSaveSci2));
			kcallOffset = 10;
		}
	} else {
		if (doRestore) {
			memcpy(patchPtr, patchGameRestoreSci21, sizeof(patchGameRestoreSci21));
			kcallOffset = 10;
		} else {
			memcpy(patchPtr, patchGameSaveSci21, sizeof(patchGameSaveSci21));
			kcallOffset = 11;
		}
	}

	patchPtr[kcallOffset] = id;
	if (g_sci->isBE()) {
		SWAP(patchPtr[kcallOffset + 1], patchPtr[kcallOffset + 2]);
	}
}
Пример #4
0
static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) {
	Script *script = segMan->getScript(methodAddress.getSegment());
	byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset()));

	memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
	patchPtr[8] = id;
}
Пример #5
0
reg_t reg_t::operator+(const reg_t right) const {
	if (isPointer() && right.isNumber()) {
		// Pointer arithmetics. Only some pointer types make sense here
		SegmentObj *mobj = g_sci->getEngineState()->_segMan->getSegmentObj(getSegment());

		if (!mobj)
			error("[VM]: Attempt to add %d to invalid pointer %04x:%04x", right.getOffset(), PRINT_REG(*this));

		switch (mobj->getType()) {
		case SEG_TYPE_LOCALS:
		case SEG_TYPE_SCRIPT:
		case SEG_TYPE_STACK:
		case SEG_TYPE_DYNMEM:
			return make_reg(getSegment(), getOffset() + right.toSint16());
		default:
			return lookForWorkaround(right, "addition");
		}
	} else if (isNumber() && right.isPointer()) {
		// Adding a pointer to a number, flip the order
		return right + *this;
	} else if (isNumber() && right.isNumber()) {
		// Normal arithmetics
		return make_reg(0, toSint16() + right.toSint16());
	} else {
		return lookForWorkaround(right, "addition");
	}
}
Пример #6
0
static void patchGameSaveRestoreCodeSci21(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) {
	Script *script = segMan->getScript(methodAddress.getSegment());
	byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset()));
	memcpy(patchPtr, patchGameRestoreSaveSci21, sizeof(patchGameRestoreSaveSci21));
	if (doRestore)
		patchPtr[2] = 0x78;	// push1
	patchPtr[9] = id;
}
Пример #7
0
static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) {
	Script *script = segMan->getScript(methodAddress.getSegment());
	byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset()));
	if (getSciVersion() <= SCI_VERSION_1_1)
		memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave));
	else	// SCI2+
		memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2));
	patchPtr[8] = id;
}
Пример #8
0
Common::Array<reg_t> Script::listAllOutgoingReferences(reg_t addr) const {
	Common::Array<reg_t> tmp;
	if (addr.getOffset() <= _buf->size() && addr.getOffset() >= (uint)-SCRIPT_OBJECT_MAGIC_OFFSET && offsetIsObject(addr.getOffset())) {
		const Object *obj = getObject(addr.getOffset());
		if (obj) {
			// Note all local variables, if we have a local variable environment
			if (_localsSegment)
				tmp.push_back(make_reg(_localsSegment, 0));

			for (uint i = 0; i < obj->getVarCount(); i++)
				tmp.push_back(obj->getVariable(i));
		} else {
			error("Request for outgoing script-object reference at %04x:%04x failed in script %d", PRINT_REG(addr), _nr);
		}
	} else {
		/*		warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/
		/* Happens e.g. when we're looking into strings */
	}
	return tmp;
}
Пример #9
0
void GfxMenu::kernelSetAttribute(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value) {
	GuiMenuItemEntry *itemEntry = findItem(menuId, itemId);

	if (!itemEntry) {
		// PQ2 demo calls this, for example, but has no menus (bug report #3034507). Some SCI
		// fan games (Al Pond 2, Aquarius) call this too on non-existent menu items. The
		// original interpreter ignored these as well.
		debugC(kDebugLevelGraphics, "Tried to setAttribute() on non-existent menu-item %d:%d", menuId, itemId);
		return;
	}

	switch (attributeId) {
	case SCI_MENU_ATTRIBUTE_ENABLED:
		itemEntry->enabled = !value.isNull();
		break;
	case SCI_MENU_ATTRIBUTE_SAID:
		itemEntry->saidVmPtr = value;
		break;
	case SCI_MENU_ATTRIBUTE_TEXT:
		itemEntry->text = _segMan->getString(value);
		itemEntry->textVmPtr = value;
		// We assume here that no script ever creates a separatorLine dynamically
		break;
	case SCI_MENU_ATTRIBUTE_KEYPRESS:
		itemEntry->keyPress = tolower(value.getOffset());
		itemEntry->keyModifier = 0;
		// TODO: Find out how modifier is handled
		debug("setAttr keypress %X %X", value.getSegment(), value.getOffset());
		break;
	case SCI_MENU_ATTRIBUTE_TAG:
		itemEntry->tag = value.getOffset();
		break;
	default:
		// Happens when loading a game in LSL3 - attribute 1A
		warning("setAttribute() called with unsupported attributeId %X", attributeId);
	}
}
Пример #10
0
uint16 Kernel::findRegType(reg_t reg) {
	// No segment? Must be integer
	if (!reg.getSegment())
		return SIG_TYPE_INTEGER | (reg.getOffset() ? 0 : SIG_TYPE_NULL);

	if (reg.getSegment() == 0xFFFF)
		return SIG_TYPE_UNINITIALIZED;

	// Otherwise it's an object
	SegmentObj *mobj = _segMan->getSegmentObj(reg.getSegment());
	if (!mobj)
		return SIG_TYPE_ERROR;

	uint16 result = 0;
	if (!mobj->isValidOffset(reg.getOffset()))
		result |= SIG_IS_INVALID;

	switch (mobj->getType()) {
	case SEG_TYPE_SCRIPT:
		if (reg.getOffset() <= (*(Script *)mobj).getBufSize() &&
			reg.getOffset() >= (uint)-SCRIPT_OBJECT_MAGIC_OFFSET &&
			(*(Script *)mobj).offsetIsObject(reg.getOffset())) {
			result |= ((Script *)mobj)->getObject(reg.getOffset()) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE;
		} else
			result |= SIG_TYPE_REFERENCE;
		break;
	case SEG_TYPE_CLONES:
		result |= SIG_TYPE_OBJECT;
		break;
	case SEG_TYPE_LOCALS:
	case SEG_TYPE_STACK:
	case SEG_TYPE_DYNMEM:
	case SEG_TYPE_HUNK:
#ifdef ENABLE_SCI32
	case SEG_TYPE_ARRAY:
	case SEG_TYPE_STRING:
#endif
		result |= SIG_TYPE_REFERENCE;
		break;
	case SEG_TYPE_LISTS:
		result |= SIG_TYPE_LIST;
		break;
	case SEG_TYPE_NODES:
		result |= SIG_TYPE_NODE;
		break;
	default:
		return SIG_TYPE_ERROR;
	}
	return result;
}
Пример #11
0
void GuestAdditions::patchGameSaveRestoreSCI32(Script &script) const {
	const ObjMap &objMap = script.getObjectMap();
	for (ObjMap::const_iterator it = objMap.begin(); it != objMap.end(); ++it) {
		const Object &obj = it->_value;
		if (strncmp(_segMan->getObjectName(obj.getPos()), "SRDialog", 8) != 0) {
			continue;
		}

		const uint16 methodCount = obj.getMethodCount();
		for (uint16 methodNr = 0; methodNr < methodCount; ++methodNr) {
			const uint16 selectorId = obj.getFuncSelector(methodNr);
			const Common::String methodName = _kernel->getSelectorName(selectorId);
			if (methodName == "doit") {
				const reg_t methodAddress = obj.getFunction(methodNr);
				byte *patchPtr = const_cast<byte *>(script.getBuf(methodAddress.getOffset()));
				memcpy(patchPtr, SRDialogPatch, sizeof(SRDialogPatch));
				break;
			}
		}
	}
}
Пример #12
0
void GfxControls32::destroyScrollWindow(const reg_t id) {
	ScrollWindow *scrollWindow = getScrollWindow(id);
	scrollWindow->hide();
	_scrollWindows.erase(id.getOffset());
	delete scrollWindow;
}