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; }
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; }
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; }
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; }