예제 #1
0
void GuestAdditions::syncPhant1UI(const int16 oldMusicVolume, const int16 musicVolume, reg_t &musicGlobal, const int16 oldDacVolume, const int16 dacVolume, reg_t &dacGlobal) const {
	const reg_t buttonId = _segMan->findObjectByName("dacVolUp");
	if (buttonId.isNull() || !_segMan->getObject(buttonId)->isInserted()) {
		// No inserted dacVolUp button means the control panel with the
		// volume controls is not visible and we can just update the values
		// and leave
		musicGlobal.setOffset(musicVolume);
		dacGlobal.setOffset(dacVolume);
		return;
	}

	reg_t thermo = _segMan->findObjectByName("midiVolThermo");
	if (!thermo.isNull()) {
		int count = ABS(musicVolume - oldMusicVolume);
		const int stepSize = (musicVolume > oldMusicVolume ? 1 : -1);
		while (count--) {
			musicGlobal.incOffset(stepSize);
			invokeSelector(thermo, SELECTOR(doit));
		}
	}

	thermo = _segMan->findObjectByName("dacVolThermo");
	if (!thermo.isNull()) {
		int count = ABS(dacVolume - oldDacVolume) / 8;
		const int stepSize = (dacVolume > oldDacVolume ? 8 : -8);
		while (count--) {
			dacGlobal.incOffset(stepSize);
			invokeSelector(thermo, SELECTOR(doit));
		}
	}
}
예제 #2
0
reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) {
	List *list = s->_segMan->lookupList(argv[0]);

	Node *curNode = s->_segMan->lookupNode(list->first);
	reg_t curObject;
	Selector slc = argv[1].toUint16();

	ObjVarRef address;

	while (curNode) {
		// We get the next node here as the current node might be gone after the invoke
		reg_t nextNode = curNode->succ;
		curObject = curNode->value;

		// First, check if the target selector is a variable
		if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
			// This can only happen with 3 params (list, target selector, variable)
			if (argc != 3) {
				error("kListEachElementDo: Attempted to modify a variable selector with %d params", argc);
			} else {
				writeSelector(s->_segMan, curObject, slc, argv[2]);
			}
		} else {
			invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);
		}

		curNode = s->_segMan->lookupNode(nextNode);
	}

	return s->r_acc;
}
예제 #3
0
reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {
	List *list = s->_segMan->lookupList(argv[0]);

	Node *curNode = s->_segMan->lookupNode(list->first);
	reg_t curObject;
	Selector slc = argv[1].toUint16();

	ObjVarRef address;

	s->r_acc = make_reg(0, 1);	// reset the accumulator

	while (curNode) {
		reg_t nextNode = curNode->succ;
		curObject = curNode->value;

		// First, check if the target selector is a variable
		if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
			// Can this happen with variable selectors?
			error("kListAllTrue: Attempted to access a variable selector");
		} else {
			invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);

			// Check if the result isn't true
			if (s->r_acc.isNull())
				break;
		}

		curNode = s->_segMan->lookupNode(nextNode);
	}

	return s->r_acc;
}
예제 #4
0
void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) {
	AnimateList::iterator it;
	const AnimateList::iterator end = _list.end();

	// This has to be done in a separate loop. At least in sq1 some .dispose
	// modifies FIXEDLOOP flag in signal for another object. In that case we
	// would overwrite the new signal with our version of the old signal.
	for (it = _list.begin(); it != end; ++it) {
		// Finally update signal
		writeSelectorValue(_s->_segMan, it->object, SELECTOR(signal), it->signal);
	}

	for (it = _list.legacy_reverse_begin(); it != end; --it) {
		// We read out signal here again, this is not by accident but to ensure
		// that we got an up-to-date signal
		it->signal = readSelectorValue(_s->_segMan, it->object, SELECTOR(signal));

		if ((it->signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) {
			_paint16->bitsRestore(readSelector(_s->_segMan, it->object, SELECTOR(underBits)));
			writeSelectorValue(_s->_segMan, it->object, SELECTOR(underBits), 0);
		}

		if (it->signal & kSignalDisposeMe) {
			// Call .delete_ method of that object
			invokeSelector(_s, it->object, SELECTOR(delete_), argc, argv, 0);
		}
	}
}
예제 #5
0
void GuestAdditions::syncMessageTypeFromScummVMUsingLSL6HiresStrategy() const {
	// LSL6hires synchronisation happens in send_selector, except when
	// restoring a game, where it happens here
	if (_state->variables[VAR_GLOBAL][kGlobalVarLSL6HiresGameFlags].isNull()) {
		return;
	}

	reg_t params[] = { make_reg(0, kLSL6HiresSubtitleFlag) };
	Selector selector;
	reg_t restore;

	if (ConfMan.getBool("subtitles")) {
		restore = TRUE_REG;
		selector = SELECTOR(clear);
	} else {
		restore = NULL_REG;
		selector = SELECTOR(set);
	}

	// Attempting to show or hide the ScrollWindow used for subtitles
	// directly (by invoking `show` or `hide`) causes the game to crash with
	// an error about passing an invalid ScrollWindow ID. Fortunately, the
	// game scripts store a flag that restores the window when a game is
	// restored
	_state->variables[VAR_GLOBAL][kGlobalVarLSL6HiresRestoreTextWindow] = restore;
	invokeSelector(_state->variables[VAR_GLOBAL][kGlobalVarLSL6HiresGameFlags], selector, 1, params);
}
예제 #6
0
reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) {
	const reg_t listReg = argv[0];
	List *list = s->_segMan->lookupList(listReg);

	Node *curNode = s->_segMan->lookupNode(list->first);
	Selector slc = argv[1].toUint16();

	ObjVarRef address;

	s->r_acc = NULL_REG;

	++list->numRecursions;

	if (list->numRecursions >= ARRAYSIZE(list->nextNodes)) {
		error("Too much recursion in kListFirstTrue");
	}

	while (curNode) {
		// We get the next node here as the current node might be deleted by the
		// invoke. In the case that the next node is also deleted, kDeleteKey
		// needs to be able to adjust the location of the next node, which is
		// why it is stored on the list instead of on the stack
		list->nextNodes[list->numRecursions] = curNode->succ;
		reg_t curObject = curNode->value;

		// First, check if the target selector is a variable
		if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
			// If it's a variable selector, check its value.
			// Example: script 64893 in Torin, MenuHandler::isHilited checks
			// all children for variable selector 0x03ba (bHilited).
			if (!readSelector(s->_segMan, curObject, slc).isNull()) {
				s->r_acc = curObject;
				break;
			}
		} else {
			invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);

			// Check if the call above leads to a game restore, in which case
			// the segment manager will be reset, and the original list will
			// be invalidated
			if (s->abortScriptProcessing == kAbortLoadGame)
				return s->r_acc;

			// Check if the result is true
			if (!s->r_acc.isNull()) {
				s->r_acc = curObject;
				break;
			}
		}

		curNode = s->_segMan->lookupNode(list->nextNodes[list->numRecursions]);
	}

	if (s->_segMan->isValidAddr(listReg, SEG_TYPE_LISTS)) {
		--list->numRecursions;
	}

	return s->r_acc;
}
예제 #7
0
void GuestAdditions::syncGK2UI() const {
	const reg_t sliderId = _segMan->findObjectByName("soundSlider");
	if (!sliderId.isNull() && _segMan->getObject(sliderId)->isInserted()) {
		const reg_t oldAcc = _state->r_acc;
		invokeSelector(sliderId, SELECTOR(initialOff));
		writeSelector(_segMan, sliderId, SELECTOR(x), _state->r_acc);
		_state->r_acc = oldAcc;
	}
}
예제 #8
0
void GuestAdditions::syncSQ6UI() const {
	const reg_t bars[] = { _segMan->findObjectByName("musicBar"),
						   _segMan->findObjectByName("soundBar") };
	for (int i = 0; i < ARRAYSIZE(bars); ++i) {
		const reg_t barId = bars[i];
		if (!barId.isNull()) {
			invokeSelector(barId, SELECTOR(show));
		}
	}
}
예제 #9
0
void GuestAdditions::syncPQ4UI(const int16 musicVolume) const {
	const SegmentId segment = _segMan->getScriptSegment(9, SCRIPT_GET_DONT_LOAD);
	if (segment != 0 && _segMan->getScript(segment)->getLocalsCount() > 2) {
		const reg_t barId = _segMan->getScript(segment)->getLocalsBegin()[2];
		if (!barId.isNull()) {
			reg_t params[] = { make_reg(0, musicVolume) };
			invokeSelector(barId, SELECTOR(setSize), 1, params);
		}
	}
}
예제 #10
0
void GuestAdditions::syncLSL6HiresUI(const int16 musicVolume) const {
	const reg_t musicDialId = _segMan->findObjectByName("volumeDial");
	if (!musicDialId.isNull()) {
		writeSelectorValue(_segMan, musicDialId, SELECTOR(curPos), musicVolume);
		writeSelectorValue(_segMan, musicDialId, SELECTOR(cel), musicVolume);
		reg_t params[] = { make_reg(0, musicVolume) };
		invokeSelector(musicDialId, SELECTOR(update), 1, params);
		if (_segMan->getObject(musicDialId)->isInserted()) {
			g_sci->_gfxFrameout->kernelUpdateScreenItem(musicDialId);
		}
	}
}
예제 #11
0
void GuestAdditions::syncTorinUI(const int16 musicVolume, const int16 sfxVolume, const int16 speechVolume) const {
	const reg_t sliders[] = { _segMan->findObjectByName("oMusicScroll"),
							  _segMan->findObjectByName("oSFXScroll"),
							  _segMan->findObjectByName("oAudioScroll") };
	const int16 values[] = { musicVolume, sfxVolume, speechVolume };
	for (int i = 0; i < ARRAYSIZE(sliders); ++i) {
		const reg_t sliderId = sliders[i];
		if (!sliderId.isNull()) {
			reg_t params[] = { make_reg(0, values[i]) };
			invokeSelector(sliderId, SELECTOR(setPos), 1, params);
		}
	}
}
예제 #12
0
파일: klists.cpp 프로젝트: OmerMor/scummvm
reg_t kSort(EngineState *s, int argc, reg_t *argv) {
	SegManager *segMan = s->_segMan;
	reg_t source = argv[0];
	reg_t dest = argv[1];
	reg_t order_func = argv[2];

	int input_size = (int16)readSelectorValue(segMan, source, SELECTOR(size));
	reg_t input_data = readSelector(segMan, source, SELECTOR(elements));
	reg_t output_data = readSelector(segMan, dest, SELECTOR(elements));

	List *list;
	Node *node;

	if (!input_size)
		return s->r_acc;

	if (output_data.isNull()) {
		list = s->_segMan->allocateList(&output_data);
		list->first = list->last = NULL_REG;
		writeSelector(segMan, dest, SELECTOR(elements), output_data);
	}

	writeSelectorValue(segMan, dest, SELECTOR(size), input_size);

	list = s->_segMan->lookupList(input_data);
	node = s->_segMan->lookupNode(list->first);

	sort_temp_t *temp_array = (sort_temp_t *)malloc(sizeof(sort_temp_t) * input_size);

	int i = 0;
	while (node) {
		reg_t params[1] = { node->value };
		invokeSelector(s, order_func, SELECTOR(doit), argc, argv, 1, params);
		temp_array[i].key = node->key;
		temp_array[i].value = node->value;
		temp_array[i].order = s->r_acc;
		i++;
		node = s->_segMan->lookupNode(node->succ);
	}

	qsort(temp_array, input_size, sizeof(sort_temp_t), sort_temp_cmp);

	for (i = 0;i < input_size;i++) {
		reg_t lNode = s->_segMan->newNode(temp_array[i].value, temp_array[i].key);
		addToEnd(s, output_data, lNode);
	}

	free(temp_array);

	return s->r_acc;
}
예제 #13
0
reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) {
	const reg_t listReg = argv[0];
	List *list = s->_segMan->lookupList(listReg);

	Node *curNode = s->_segMan->lookupNode(list->first);
	Selector slc = argv[1].toUint16();

	ObjVarRef address;

	++list->numRecursions;

	if (list->numRecursions >= ARRAYSIZE(list->nextNodes)) {
		error("Too much recursion in kListEachElementDo");
	}

	while (curNode) {
		// We get the next node here as the current node might be deleted by the
		// invoke. In the case that the next node is also deleted, kDeleteKey
		// needs to be able to adjust the location of the next node, which is
		// why it is stored on the list instead of on the stack
		list->nextNodes[list->numRecursions] = curNode->succ;
		reg_t curObject = curNode->value;

		// First, check if the target selector is a variable
		if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
			// This can only happen with 3 params (list, target selector, variable)
			if (argc != 3) {
				error("kListEachElementDo: Attempted to modify a variable selector with %d params", argc);
			} else {
				writeSelector(s->_segMan, curObject, slc, argv[2]);
			}
		} else {
			invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);

			// Check if the call above leads to a game restore, in which case
			// the segment manager will be reset, and the original list will
			// be invalidated
			if (s->abortScriptProcessing == kAbortLoadGame)
				return s->r_acc;
		}

		curNode = s->_segMan->lookupNode(list->nextNodes[list->numRecursions]);
	}

	if (s->_segMan->isValidAddr(listReg, SEG_TYPE_LISTS)) {
		--list->numRecursions;
	}

	return s->r_acc;
}
예제 #14
0
void GuestAdditions::syncGK2VolumeFromScummVM(const int16 musicVolume) const {
	_state->variables[VAR_GLOBAL][kGlobalVarGK2MusicVolume] = make_reg(0, musicVolume);

	// Calling `setVol` on all sounds is necessary to propagate the volume
	// change to existing sounds, and matches how game scripts propagate
	// volume changes when the in-game music slider is moved
	const reg_t soundsId = _state->variables[VAR_GLOBAL][kGlobalVarSounds];
	if (!soundsId.isNull()) {
		List *sounds = _segMan->lookupList(readSelector(_segMan, soundsId, SELECTOR(elements)));
		reg_t soundId = sounds->first;
		while (!soundId.isNull()) {
			Node *sound = _segMan->lookupNode(soundId);
			reg_t params[] = { make_reg(0, musicVolume) };
			invokeSelector(sound->value, SELECTOR(setVol), 1, params);
			soundId = sound->succ;
		}
	}
}
예제 #15
0
파일: klists.cpp 프로젝트: OmerMor/scummvm
reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {
	List *list = s->_segMan->lookupList(argv[0]);

	Node *curNode = s->_segMan->lookupNode(list->first);
	reg_t curObject;
	Selector slc = argv[1].toUint16();

	ObjVarRef address;

	s->r_acc = TRUE_REG;

	++list->numRecursions;

	if (list->numRecursions >= ARRAYSIZE(list->nextNodes)) {
		error("Too much recursion in kListAllTrue");
	}

	while (curNode) {
		// We get the next node here as the current node might be deleted by the
		// invoke. In the case that the next node is also deleted, kDeleteKey
		// needs to be able to adjust the location of the next node, which is
		// why it is stored on the list instead of on the stack
		list->nextNodes[list->numRecursions] = curNode->succ;
		curObject = curNode->value;

		// First, check if the target selector is a variable
		if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
			// If it's a variable selector, check its value
			s->r_acc = readSelector(s->_segMan, curObject, slc);
		} else {
			invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);
		}

		// Check if the result isn't true
		if (s->r_acc.isNull())
			break;

		curNode = s->_segMan->lookupNode(list->nextNodes[list->numRecursions]);
	}

	--list->numRecursions;

	return s->r_acc;
}
예제 #16
0
파일: animate.cpp 프로젝트: Cruel/scummvm
bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
	reg_t curAddress = list->first;
	Node *curNode = _s->_segMan->lookupNode(curAddress);
	reg_t curObject;
	uint16 signal;

	while (curNode) {
		curObject = curNode->value;

		if (_fastCastEnabled) {
			// Check if the game has a fastCast object set
			//  if we don't abort kAnimate processing, at least in kq5 there will be animation cels drawn into speech boxes.
			if (!_s->variables[VAR_GLOBAL][84].isNull()) {
				// This normally points to an object called "fastCast",
				// but for example in Eco Quest 1 it may also point to an object called "EventHandler" (see bug #5170)
				// Original SCI only checked, if this global was not 0.
				return false;
			}
		}

		signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal));
		if (!(signal & kSignalFrozen)) {
			// Call .doit method of that object
			invokeSelector(_s, curObject, SELECTOR(doit), argc, argv, 0);

			// If a game is being loaded, stop processing
			if (_s->abortScriptProcessing != kAbortNone)
				return true; // Stop processing

			// Lookup node again, since the nodetable it was in may have been reallocated.
			// The node might have been deallocated at this point (e.g. LSL2, room 42),
			// in which case the node reference will be null and the loop will stop below.
			// If the node is deleted from kDeleteKey, it won't have a successor node, thus
			// list processing will stop here (which is what SSCI does).
			curNode = _s->_segMan->lookupNode(curAddress, false);
		}

		if (curNode) {
			curAddress = curNode->succ;
			curNode = _s->_segMan->lookupNode(curAddress);
		}
	}
	return true;
}
예제 #17
0
void GuestAdditions::syncGK1UI() const {
	const reg_t bars[] = { _segMan->findObjectByName("musicBar"),
						   _segMan->findObjectByName("soundBar") };

	for (int i = 0; i < ARRAYSIZE(bars); ++i) {
		const reg_t barId = bars[i];
		if (!barId.isNull()) {
			// Resetting the position to 0 causes the bar to refresh its
			// position when it next draws
			writeSelectorValue(_segMan, barId, SELECTOR(position), 0);

			// The `signal` property indicates bar visibility (for some
			// reason, the normal `-info-` flag is not used)
			if (readSelectorValue(_segMan, barId, SELECTOR(signal)) & 0x20) {
				// `show` pulls a new value from the underlying sound object
				// and refreshes the bar rendering
				invokeSelector(barId, SELECTOR(show));
			}
		}
	}
}
예제 #18
0
reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) {
	List *list = s->_segMan->lookupList(argv[0]);

	Node *curNode = s->_segMan->lookupNode(list->first);
	reg_t curObject;
	Selector slc = argv[1].toUint16();

	ObjVarRef address;

	s->r_acc = NULL_REG;	// reset the accumulator

	while (curNode) {
		reg_t nextNode = curNode->succ;
		curObject = curNode->value;

		// First, check if the target selector is a variable
		if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) {
			// If it's a variable selector, check its value.
			// Example: script 64893 in Torin, MenuHandler::isHilited checks
			// all children for variable selector 0x03ba (bHilited).
			if (!readSelector(s->_segMan, curObject, slc).isNull())
				return curObject;
		} else {
			invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2);

			// Check if the result is true
			if (!s->r_acc.isNull())
				return curObject;
		}

		curNode = s->_segMan->lookupNode(nextNode);
	}

	// No selector returned true
	return NULL_REG;
}
예제 #19
0
void GuestAdditions::syncTorinVolumeFromScummVM(const int16 musicVolume, const int16 sfxVolume, const int16 speechVolume) const {
	_state->variables[VAR_GLOBAL][kGlobalVarTorinMusicVolume]  = make_reg(0, musicVolume);
	_state->variables[VAR_GLOBAL][kGlobalVarTorinSFXVolume]    = make_reg(0, sfxVolume);
	_state->variables[VAR_GLOBAL][kGlobalVarTorinSpeechVolume] = make_reg(0, speechVolume);

	// Calling `reSyncVol` on all sounds is necessary to propagate the
	// volume change to existing sounds, and matches how game scripts
	// propagate volume changes when the in-game volume sliders are moved
	const reg_t soundsId = _state->variables[VAR_GLOBAL][kGlobalVarSounds];
	if (!soundsId.isNull()) {
		const Selector selector = SELECTOR(reSyncVol);
		List *sounds = _segMan->lookupList(readSelector(_segMan, soundsId, SELECTOR(elements)));
		reg_t soundId = sounds->first;
		while (!soundId.isNull()) {
			Node *sound = _segMan->lookupNode(soundId);
			const reg_t &soundObj = sound->value;

			if (_segMan->isHeapObject(soundObj) && lookupSelector(_segMan, soundObj, selector, nullptr, nullptr) != kSelectorNone) {
				invokeSelector(sound->value, SELECTOR(reSyncVol));
			}
			soundId = sound->succ;
		}
	}
}
예제 #20
0
reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
	int mask = argv[0].toUint16();
	reg_t obj = argv[1];
	SciEvent curEvent;
	int modifier_mask = getSciVersion() <= SCI_VERSION_01 ? SCI_KEYMOD_ALL : SCI_KEYMOD_NO_FOOLOCK;
	uint16 modifiers = 0;
	SegManager *segMan = s->_segMan;
	Common::Point mousePos;

	// For Mac games with an icon bar, handle possible icon bar events first
	if (g_sci->hasMacIconBar()) {
		reg_t iconObj = g_sci->_gfxMacIconBar->handleEvents();
		if (!iconObj.isNull())
			invokeSelector(s, iconObj, SELECTOR(select), argc, argv, 0, NULL);
	}

	// If there's a simkey pending, and the game wants a keyboard event, use the
	// simkey instead of a normal event
	if (g_debug_simulated_key && (mask & SCI_EVENT_KEYBOARD)) {
		// In case we use a simulated event we query the current mouse position
		mousePos = g_sci->_gfxCursor->getPosition();
#ifdef ENABLE_SCI32
		if (getSciVersion() >= SCI_VERSION_2_1_EARLY)
			g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
#endif
		// Limit the mouse cursor position, if necessary
		g_sci->_gfxCursor->refreshPosition();

		writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD); // Keyboard event
		writeSelectorValue(segMan, obj, SELECTOR(message), g_debug_simulated_key);
		writeSelectorValue(segMan, obj, SELECTOR(modifiers), SCI_KEYMOD_NUMLOCK); // Numlock on
		writeSelectorValue(segMan, obj, SELECTOR(x), mousePos.x);
		writeSelectorValue(segMan, obj, SELECTOR(y), mousePos.y);
		g_debug_simulated_key = 0;
		return make_reg(0, 1);
	}
	
	curEvent = g_sci->getEventManager()->getSciEvent(mask);

	if (s->_delayedRestoreGame) {
		// delayed restore game from ScummVM menu got triggered
		gamestate_delayedrestore(s);
		return NULL_REG;
	}

	// For a real event we use its associated mouse position
	mousePos = curEvent.mousePos;
#ifdef ENABLE_SCI32
	if (getSciVersion() >= SCI_VERSION_2_1_EARLY)
		g_sci->_gfxCoordAdjuster->fromDisplayToScript(mousePos.y, mousePos.x);
#endif
	// Limit the mouse cursor position, if necessary
	g_sci->_gfxCursor->refreshPosition();

	if (g_sci->getVocabulary())
		g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event

	if (s->_cursorWorkaroundActive) {
		// We check if the actual cursor position is inside specific rectangles
		// where the cursor itself should be moved to. If this is the case, we
		// set the mouse cursor's position to be within the rectangle in
		// question. Check GfxCursor::setPosition(), for a more detailed
		// explanation and a list of cursor position workarounds.
		if (s->_cursorWorkaroundRect.contains(mousePos.x, mousePos.y)) {
			s->_cursorWorkaroundActive = false;
		} else {
			mousePos.x = s->_cursorWorkaroundPoint.x;
			mousePos.y = s->_cursorWorkaroundPoint.y;
		}
	}

	writeSelectorValue(segMan, obj, SELECTOR(x), mousePos.x);
	writeSelectorValue(segMan, obj, SELECTOR(y), mousePos.y);

	// Get current keyboard modifiers, only keep relevant bits
	modifiers = curEvent.modifiers & modifier_mask;
	if (g_sci->getPlatform() == Common::kPlatformDOS) {
		// We are supposed to emulate SCI running in DOS

		// We set the higher byte of the modifiers to 02h
		// Original SCI also did that indirectly, because it asked BIOS for shift status
		// via AH=0x02 INT16, which then sets the shift flags in AL
		// AH is supposed to be destroyed in that case and it's not defined that 0x02
		// is still in it on return. The value of AX was then set into the modifiers selector.
		// At least one fan-made game (Betrayed Alliance) requires 0x02 to be in the upper byte,
		// otherwise the darts game (script 111) will not work properly.

		// It seems Sierra fixed this behaviour (effectively bug) in the SCI1 keyboard driver.
		// SCI32 also resets the upper byte.
		if (getSciVersion() <= SCI_VERSION_01) {
			modifiers |= 0x0200;
		}
	}

	//s->_gui->moveCursor(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y);

	switch (curEvent.type) {
	case SCI_EVENT_QUIT:
		s->abortScriptProcessing = kAbortQuitGame; // Terminate VM
		g_sci->_debugState.seeking = kDebugSeekNothing;
		g_sci->_debugState.runningStep = 0;
		break;

	case SCI_EVENT_KEYBOARD:
		writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD); // Keyboard event
		s->r_acc = make_reg(0, 1);

		writeSelectorValue(segMan, obj, SELECTOR(message), curEvent.character);
		// We only care about the translated character
		writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
		break;

	case SCI_EVENT_MOUSE_RELEASE:
	case SCI_EVENT_MOUSE_PRESS:

		// track left buttton clicks, if requested
		if (curEvent.type == SCI_EVENT_MOUSE_PRESS && curEvent.data == 1 && g_debug_track_mouse_clicks) {
			g_sci->getSciDebugger()->debugPrintf("Mouse clicked at %d, %d\n",
						mousePos.x, mousePos.y);
		}

		if (mask & curEvent.type) {
			int extra_bits = 0;

			switch (curEvent.data) {
			case 2:
				extra_bits = SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT;
				break;
			case 3:
				extra_bits = SCI_KEYMOD_CTRL;
			default:
				break;
			}
			modifiers |= extra_bits; // add these additional bits to the mix

			writeSelectorValue(segMan, obj, SELECTOR(type), curEvent.type);
			writeSelectorValue(segMan, obj, SELECTOR(message), 0);
			writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
			s->r_acc = make_reg(0, 1);
		}
		break;

	default:
		// Return a null event
		writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_NONE);
		writeSelectorValue(segMan, obj, SELECTOR(message), 0);
		writeSelectorValue(segMan, obj, SELECTOR(modifiers), modifiers);
		s->r_acc = NULL_REG;
	}

	if ((s->r_acc.getOffset()) && (g_sci->_debugState.stopOnEvent)) {
		g_sci->_debugState.stopOnEvent = false;

		// A SCI event occurred, and we have been asked to stop, so open the debug console
		Console *con = g_sci->getSciDebugger();
		con->debugPrintf("SCI event occurred: ");
		switch (curEvent.type) {
		case SCI_EVENT_QUIT:
			con->debugPrintf("quit event\n");
			break;
		case SCI_EVENT_KEYBOARD:
			con->debugPrintf("keyboard event\n");
			break;
		case SCI_EVENT_MOUSE_RELEASE:
		case SCI_EVENT_MOUSE_PRESS:
			con->debugPrintf("mouse click event\n");
			break;
		default:
			con->debugPrintf("unknown or no event (event type %d)\n", curEvent.type);
		}

		con->attach();
		con->onFrame();
	}

	if (g_sci->_features->detectDoSoundType() <= SCI_VERSION_0_LATE) {
		// If we're running a sound-SCI0 game, update the sound cues, to
		// compensate for the fact that sound-SCI0 does not poll to update
		// the sound cues itself, like sound-SCI1 and later do with
		// cmdUpdateSoundCues. kGetEvent is called quite often, so emulate
		// the sound-SCI1 behavior of cmdUpdateSoundCues with this call
		g_sci->_soundCmd->updateSci0Cues();
	}

	// Wait a bit here, so that the CPU isn't maxed out when the game
	// is waiting for user input (e.g. when showing text boxes) - bug
	// #3037874. Make sure that we're not delaying while the game is
	// benchmarking, as that will affect the final benchmarked result -
	// check bugs #3058865 and #3127824
	if (s->_gameIsBenchmarking) {
		// Game is benchmarking, don't add a delay
	} else {
		g_system->delayMillis(10);
	}

	return s->r_acc;
}
예제 #21
0
파일: kparse.cpp 프로젝트: Cruel/scummvm
reg_t kParse(EngineState *s, int argc, reg_t *argv) {
	SegManager *segMan = s->_segMan;
	reg_t stringpos = argv[0];
	Common::String string = s->_segMan->getString(stringpos);
	char *error;
	reg_t event = argv[1];
	g_sci->checkVocabularySwitch();
	Vocabulary *voc = g_sci->getVocabulary();
	voc->parser_event = event;
	reg_t params[2] = { s->_segMan->getParserPtr(), stringpos };

	ResultWordListList words;
	bool res = voc->tokenizeString(words, string.c_str(), &error);
	voc->parserIsValid = false; /* not valid */

	if (res && !words.empty()) {
		voc->synonymizeTokens(words);

		s->r_acc = make_reg(0, 1);

#ifdef DEBUG_PARSER
		debugC(kDebugLevelParser, "Parsed to the following blocks:");

		for (ResultWordListList::const_iterator i = words.begin(); i != words.end(); ++i) {
			debugCN(2, kDebugLevelParser, "   ");
			for (ResultWordList::const_iterator j = i->begin(); j != i->end(); ++j) {
				debugCN(2, kDebugLevelParser, "%sType[%04x] Group[%04x]", j == i->begin() ? "" : " / ", j->_class, j->_group);
			}
			debugCN(2, kDebugLevelParser, "\n");
		}
#endif

		voc->replacePronouns(words);

		int syntax_fail = voc->parseGNF(words);

		if (syntax_fail) {
			s->r_acc = make_reg(0, 1);
			writeSelectorValue(segMan, event, SELECTOR(claimed), 1);

			invokeSelector(s, g_sci->getGameObject(), SELECTOR(syntaxFail), argc, argv, 2, params);
			/* Issue warning */

			debugC(kDebugLevelParser, "Tree building failed");

		} else {
			voc->parserIsValid = true;
			voc->storePronounReference();
			writeSelectorValue(segMan, event, SELECTOR(claimed), 0);

#ifdef DEBUG_PARSER
			voc->dumpParseTree();
#endif
		}

	} else {

		s->r_acc = make_reg(0, 0);
		writeSelectorValue(segMan, event, SELECTOR(claimed), 1);

		if (error) {
			s->_segMan->strcpy(s->_segMan->getParserPtr(), error);
			debugC(kDebugLevelParser, "Word unknown: %s", error);
			/* Issue warning: */

			invokeSelector(s, g_sci->getGameObject(), SELECTOR(wordFail), argc, argv, 2, params);
			free(error);
			return make_reg(0, 1); /* Tell them that it didn't work */
		}
	}

	return s->r_acc;
}
예제 #22
0
void GuestAdditions::syncPQSWATUI() const {
	const reg_t barId = _segMan->findObjectByName("volumeLed");
	if (!barId.isNull() && _segMan->getObject(barId)->isInserted()) {
		invokeSelector(barId, SELECTOR(displayValue));
	}
}
예제 #23
0
bool GuestAdditions::restoreFromLauncher() const {
	assert(_state->_delayedRestoreGameId != -1);

#ifdef ENABLE_SCI32
	if (getSciVersion() >= SCI_VERSION_2) {
		if (_restoring) {
			// Recursion will occur if a restore fails, as
			// _delayedRestoreGameId will not be reset so the kernel will try
			// to keep restoring forever
			_state->_delayedRestoreGameId = -1;
			_restoring = false;
			return false;
		}

		// Delayed restore should not happen until after the benchmarking room.
		// In particular, in SQ6, delayed restore must not happen until room 100
		// (the Sierra logo & main menu room), otherwise the game scripts will
		// try to make calls to the subtitles ScrollWindow, which does not
		// exist. In other games, restoring early either breaks benchmarking,
		// or, when trying to load an invalid save game, makes the dialog
		// telling the user that the game is invalid impossible to read
		if (strcmp(_segMan->getObjectName(_state->variables[VAR_GLOBAL][kGlobalVarCurrentRoom]), "speedRoom") == 0) {
			return false;
		}

		_restoring = true;

		if (g_sci->getGameId() == GID_SHIVERS) {
			// Shivers accepts the save game number as a parameter to
			// `SHIVERS::restore`
			reg_t args[] = { make_reg(0, _state->_delayedRestoreGameId - kSaveIdShift) };
			invokeSelector(g_sci->getGameObject(), SELECTOR(restore), 1, args);
		} else {
			// When `Game::restore` is invoked, it will call to `Restore::doit`
			// which will automatically return the `_delayedRestoreGameId` instead
			// of prompting the user for a save game
			invokeSelector(g_sci->getGameObject(), SELECTOR(restore));
		}

		_restoring = false;

		return true;
	} else {
#else
	{
#endif
		int savegameId = _state->_delayedRestoreGameId; // delayedRestoreGameId gets destroyed within gamestate_restore()!
		Common::String fileName = g_sci->getSavegameName(savegameId);
		Common::SeekableReadStream *in = g_sci->getSaveFileManager()->openForLoading(fileName);

		if (in) {
			// found a savegame file
			gamestate_restore(_state, in);
			delete in;
			if (_state->r_acc != make_reg(0, 1)) {
				gamestate_afterRestoreFixUp(_state, savegameId);
				return true;
			}
		}

		error("Restoring gamestate '%s' failed", fileName.c_str());
	}
}

#pragma mark -
#pragma mark Message type sync

void GuestAdditions::syncMessageTypeFromScummVM() const {
	switch (_features->getMessageTypeSyncStrategy()) {
	case kMessageTypeSyncStrategyDefault:
		syncMessageTypeFromScummVMUsingDefaultStrategy();
		break;

#ifdef ENABLE_SCI32
	case kMessageTypeSyncStrategyShivers:
		syncMessageTypeFromScummVMUsingShiversStrategy();
		break;

	case kMessageTypeSyncStrategyLSL6Hires:
		syncMessageTypeFromScummVMUsingLSL6HiresStrategy();
		break;
#endif
	case kMessageTypeSyncStrategyNone:
		break;
	}
}

void GuestAdditions::syncMessageTypeFromScummVMUsingDefaultStrategy() const {
	uint8 value = 0;
	if (ConfMan.getBool("subtitles")) {
		value |= kMessageTypeSubtitles;
	}
	if (!ConfMan.getBool(("speech_mute"))) {
		value |= kMessageTypeSpeech;
	}

	if (value == kMessageTypeSubtitles + kMessageTypeSpeech && !_features->supportsSpeechWithSubtitles()) {
		value &= ~kMessageTypeSubtitles;
	}

	if (value) {
		_state->variables[VAR_GLOBAL][kGlobalVarMessageType] = make_reg(0, value);
	}

	if (g_sci->getGameId() == GID_GK1) {
		if (value == kMessageTypeSubtitles) {
			_state->variables[VAR_GLOBAL][kGlobalVarGK1NarratorMode] = NULL_REG;
		} else if (value == kMessageTypeSpeech) {
			_state->variables[VAR_GLOBAL][kGlobalVarGK1NarratorMode] = TRUE_REG;
		}
	}
}