Example #1
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;
	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)
			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);

	// For a real event we use its associated mouse position
	mousePos = curEvent.mousePos;
#ifdef ENABLE_SCI32
	if (getSciVersion() >= SCI_VERSION_2_1)
		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);

	//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), curEvent.modifiers & modifier_mask);
		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;
			}

			writeSelectorValue(segMan, obj, SELECTOR(type), curEvent.type);
			writeSelectorValue(segMan, obj, SELECTOR(message), 0);
			writeSelectorValue(segMan, obj, SELECTOR(modifiers), (curEvent.modifiers | extra_bits) & modifier_mask);
			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), curEvent.modifiers & modifier_mask);
		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;
}
Example #2
0
int Vocabulary::parseGNF(const ResultWordListList &words, bool verbose) {
	Console *con = g_sci->getSciDebugger();
	// Get the start rules:
	ParseRuleList *work = _vocab_clone_rule_list_by_id(_parserRules, _parserBranches[0].data[1]);
	ParseRuleList *results = NULL;
	uint word = 0;
	const uint words_nr = words.size();
	ResultWordListList::const_iterator words_iter;

	for (words_iter = words.begin(); words_iter != words.end(); ++words_iter, ++word) {
		ParseRuleList *new_work = NULL;
		ParseRuleList *reduced_rules = NULL;
		ParseRuleList *seeker, *subseeker;

		if (verbose)
			con->DebugPrintf("Adding word %d...\n", word);

		seeker = work;
		while (seeker) {
			if (seeker->rule->_numSpecials <= (words_nr - word)) {
				reduced_rules = _vocab_add_rule(reduced_rules, _vsatisfy_rule(seeker->rule, *words_iter));
			}

			seeker = seeker->next;
		}

		if (reduced_rules == NULL) {
			freeRuleList(work);
			if (verbose)
				con->DebugPrintf("No results.\n");
			return 1;
		}

		freeRuleList(work);

		if (word + 1 < words_nr) {
			seeker = reduced_rules;

			while (seeker) {
				if (seeker->rule->_numSpecials) {
					int my_id = seeker->rule->_data[seeker->rule->_firstSpecial];

					subseeker = _parserRules;
					while (subseeker) {
						if (subseeker->rule->_id == my_id)
							new_work = _vocab_add_rule(new_work, _vinsert(seeker->rule, subseeker->rule));

						subseeker = subseeker->next;
					}
				}

				seeker = seeker->next;
			}
			freeRuleList(reduced_rules);
		} else // last word
			new_work = reduced_rules;

		work = new_work;
		if (verbose)
			con->DebugPrintf("Now at %d candidates\n", _vocab_rule_list_length(work));
		if (work == NULL) {
			if (verbose)
				con->DebugPrintf("No results.\n");
			return 1;
		}
	}

	results = work;

	if (verbose) {
		con->DebugPrintf("All results (excluding the surrounding '(141 %03x' and ')'):\n", _parserBranches[0].id);
		results->print();
		con->DebugPrintf("\n");
	}

	// now use the first result
	{
		int temp, pos;

		_parserNodes[0].type = kParseTreeBranchNode;
		_parserNodes[0].left = &_parserNodes[1];
		_parserNodes[0].right = &_parserNodes[2];

		_parserNodes[1].type = kParseTreeLeafNode;
		_parserNodes[1].value = 0x141;
		_parserNodes[1].right = 0;

		_parserNodes[2].type = kParseTreeBranchNode;
		_parserNodes[2].left = 0;
		_parserNodes[2].right = 0;

		pos = 2;

		temp = _vbpt_append(_parserNodes, &pos, 2, _parserBranches[0].id);
		//_vbpt_write_subexpression(nodes, &pos, results[_vocab_rule_list_length(results)].rule, 0, temp);
		_vbpt_write_subexpression(_parserNodes, &pos, results->rule, 0, temp);
	}

	freeRuleList(results);

	return 0;
}
Example #3
0
reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) {
	int mask = argv[0].toUint16();
	reg_t obj = argv[1];
	sci_event_t e;
	int oldx, oldy;
	int modifier_mask = s->_version <= SCI_VERSION_0 ? SCI_EVM_ALL : SCI_EVM_NO_FOOLOCK;

	if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) {
		// Penalty time- too many requests to this function without waiting!
		int delay = s->script_000->locals_block->_locals[SCI_VARIABLE_GAME_SPEED].offset;
		gfxop_sleep(s->gfx_state, delay * 1000 / 60);
	}

	// 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_EVT_KEYBOARD)) {
		PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event
		PUT_SEL32V(obj, message, g_debug_simulated_key);
		PUT_SEL32V(obj, modifiers, SCI_EVM_NUMLOCK); // Numlock on
		PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x);
		PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y);
		g_debug_simulated_key = 0;
		return make_reg(0, 1);
	}

	oldx = s->gfx_state->pointer_pos.x;
	oldy = s->gfx_state->pointer_pos.y;
	e = gfxop_get_event(s->gfx_state, mask);

	s->parser_event = NULL_REG; // Invalidate parser event

	PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x);
	PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y);

	//gfxop_set_pointer_position(s->gfx_state, Common::Point(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y));

	if (e.type)
		s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT | KERNEL_OPT_FLAG_GOT_2NDEVENT);
	else {
		if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_EVENT)
			s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_2NDEVENT;
		else
			s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_EVENT;
	}

	switch (e.type) {
	case SCI_EVT_QUIT:
		quit_vm();
		break;

	case SCI_EVT_KEYBOARD:
		if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) && (e.data == '-')) {
			printf("Debug mode activated\n");
			scriptState.seeking = kDebugSeekNothing;
			scriptState.runningStep = 0;
		} else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) {
			printf("Debug mode activated\n");
			scriptState.seeking = kDebugSeekNothing;
			scriptState.runningStep = 0;
		} else {
			PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event
			s->r_acc = make_reg(0, 1);
			PUT_SEL32V(obj, message, e.character);
			// We only care about the translated
			// character
			PUT_SEL32V(obj, modifiers, e.buckybits&modifier_mask);
		}
		break;

	case SCI_EVT_MOUSE_RELEASE:
	case SCI_EVT_MOUSE_PRESS: {
		int extra_bits = 0;

		// track left buttton clicks, if requested
		if (e.type == SCI_EVT_MOUSE_PRESS && e.data == 1 && g_debug_track_mouse_clicks) {
			((SciEngine *)g_engine)->getSciDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", 
						s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y);
		}

		if (mask & e.type) {
			switch (e.data) {
			case 2:
				extra_bits = SCI_EVM_LSHIFT | SCI_EVM_RSHIFT;
				break;
			case 3:
				extra_bits = SCI_EVM_CTRL;
			default:
				break;
			}

			PUT_SEL32V(obj, type, e.type);
			PUT_SEL32V(obj, message, 1);
			PUT_SEL32V(obj, modifiers, (e.buckybits | extra_bits)&modifier_mask);
			s->r_acc = make_reg(0, 1);
		}
		break;
	}

	default:
		s->r_acc = NULL_REG; // Unknown or no event
	}

	if ((s->r_acc.offset) && (scriptState.stopOnEvent)) {
		scriptState.stopOnEvent = false;

		// A SCI event occured, and we have been asked to stop, so open the debug console
		Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger();
		con->DebugPrintf("SCI event occured: ");
		switch (e.type) {
		case SCI_EVT_QUIT:
			con->DebugPrintf("quit event\n");
			break;
		case SCI_EVT_KEYBOARD:
			con->DebugPrintf("keyboard event\n");
			break;
		case SCI_EVT_MOUSE_RELEASE:
		case SCI_EVT_MOUSE_PRESS:
			con->DebugPrintf("mouse click event\n");
			break;
		default:
			con->DebugPrintf("unknown or no event (event type %d)\n", e.type);
		}

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

	return s->r_acc;
}
Example #4
0
ParseRuleList *Vocabulary::buildGNF(bool verbose) {
	int iterations = 0;
	int last_termrules, termrules = 0;
	int ntrules_nr;
	ParseRuleList *ntlist = NULL;
	ParseRuleList *tlist, *new_tlist;
	Console *con = g_sci->getSciDebugger();

	for (uint i = 1; i < _parserBranches.size(); i++) { // branch rule 0 is treated specially
		ParseRule *rule = _vbuild_rule(&_parserBranches[i]);
		if (!rule)
			return NULL;
		ntlist = _vocab_add_rule(ntlist, rule);
	}

	tlist = _vocab_split_rule_list(ntlist);
	ntrules_nr = _vocab_rule_list_length(ntlist);

	if (verbose)
		con->DebugPrintf("Starting with %d rules\n", ntrules_nr);

	new_tlist = tlist;
	tlist = NULL;

	do {
		ParseRuleList *new_new_tlist = NULL;
		ParseRuleList *ntseeker, *tseeker;
		last_termrules = termrules;

		ntseeker = ntlist;
		while (ntseeker) {
			tseeker = new_tlist;

			while (tseeker) {
				ParseRule *newrule = _vinsert(ntseeker->rule, tseeker->rule);
				if (newrule)
					new_new_tlist = _vocab_add_rule(new_new_tlist, newrule);
				tseeker = tseeker->next;
			}

			ntseeker = ntseeker->next;
		}

		tlist = _vocab_merge_rule_lists(tlist, new_tlist);
		new_tlist = new_new_tlist;
		termrules = _vocab_rule_list_length(new_new_tlist);

		if (verbose)
			con->DebugPrintf("After iteration #%d: %d new term rules\n", ++iterations, termrules);

	} while (termrules && (iterations < 30));

	freeRuleList(ntlist);

	if (verbose) {
		con->DebugPrintf("\nGNF rules:\n");
		tlist->print();
		con->DebugPrintf("%d allocd rules\n", _allocd_rules);
		con->DebugPrintf("Freeing rule list...\n");
		freeRuleList(tlist);
		return NULL;
	}

	return tlist;
}