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; }
SciEvent EventManager::getScummVMEvent() { SciEvent input = { SCI_EVENT_NONE, 0, 0, 0, Common::Point(0, 0) }; SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, 0, Common::Point(0, 0) }; Common::EventManager *em = g_system->getEventManager(); Common::Event ev; bool found = em->pollEvent(ev); // Don't generate events for mouse movement while (found && ev.type == Common::EVENT_MOUSEMOVE) found = em->pollEvent(ev); // Save the mouse position // // We call getMousePos of the event manager here, since we also want to // store the mouse position in case of keyboard events, which do not feature // any mouse position information itself. // This should be safe, since the mouse position in the event manager should // only be updated when a mouse related event has been taken from the queue // via pollEvent. // We also adjust the position based on the scaling of the screen. Common::Point mousePos = em->getMousePos(); g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x); noEvent.mousePos = input.mousePos = mousePos; if (!found || ev.type == Common::EVENT_MOUSEMOVE) { int modifiers = em->getModifierState(); noEvent.modifiers = ((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) | ((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) | ((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0); return noEvent; } if (ev.type == Common::EVENT_QUIT) { input.type = SCI_EVENT_QUIT; return input; } // Handle mouse events for (int i = 0; i < ARRAYSIZE(mouseEventMappings); i++) { if (mouseEventMappings[i].commonType == ev.type) { input.type = mouseEventMappings[i].sciType; input.data = mouseEventMappings[i].data; return input; } } // If we reached here, make sure that it's a keydown event if (ev.type != Common::EVENT_KEYDOWN) return noEvent; // Check for Control-D (debug console) if (ev.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_SHIFT) && ev.kbd.keycode == Common::KEYCODE_d) { // Open debug console Console *con = g_sci->getSciDebugger(); con->attach(); return noEvent; } // Process keyboard events int modifiers = em->getModifierState(); bool numlockOn = (ev.kbd.flags & Common::KBD_NUM); input.data = ev.kbd.keycode; input.character = ev.kbd.ascii; input.type = SCI_EVENT_KEYBOARD; input.modifiers = ((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) | ((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) | ((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0); // Caps lock and Scroll lock have been removed, cause we already handle upper // case keys ad Scroll lock doesn't seem to be used anywhere //((ev.kbd.flags & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) | //((ev.kbd.flags & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) | if ((input.character) && (input.character <= 0xFF)) { // Directly accept most common keys without conversion if ((input.character >= 0x80) && (input.character <= 0xFF)) { // If there is no extended font, we will just clear the // current event. // Sierra SCI actually accepted those characters, but // didn't display them inside text edit controls because // the characters were missing inside the font(s). // We filter them out for non-multilingual games because // of that. if (!_fontIsExtended) return noEvent; // Convert 8859-1 characters to DOS (cp850/437) for // multilingual SCI01 games input.character = codepagemap_88591toDOS[input.character & 0x7f]; } if (input.data == Common::KEYCODE_TAB) { input.character = input.data = SCI_KEY_TAB; if (modifiers & Common::KBD_SHIFT) input.character = SCI_KEY_SHIFT_TAB; } if (input.data == Common::KEYCODE_DELETE) input.data = input.character = SCI_KEY_DELETE; } else if ((input.data >= Common::KEYCODE_F1) && input.data <= Common::KEYCODE_F10) { // SCI_K_F1 == 59 << 8 // SCI_K_SHIFT_F1 == 84 << 8 input.character = input.data = SCI_KEY_F1 + ((input.data - Common::KEYCODE_F1)<<8); if (modifiers & Common::KBD_SHIFT) input.character = input.data + 0x1900; } else { // Special keys that need conversion for (int i = 0; i < ARRAYSIZE(keyMappings); i++) { if (keyMappings[i].scummVMKey == ev.kbd.keycode) { input.character = input.data = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff; break; } } } // When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give // us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway // we support the other case as well if ((modifiers & Common::KBD_ALT) && input.character > 0 && input.character < 27) input.character += 96; // 0x01 -> 'a' // Scancodify if appropriate if (modifiers & Common::KBD_ALT) input.character = altify(input.character); if (getSciVersion() <= SCI_VERSION_1_MIDDLE && (modifiers & Common::KBD_CTRL) && input.character > 0 && input.character < 27) input.character += 96; // 0x01 -> 'a' // If no actual key was pressed (e.g. if only a modifier key was pressed), // ignore the event if (!input.character) return noEvent; return input; }
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; }
SciEvent EventManager::getScummVMEvent() { #ifdef ENABLE_SCI32 SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() }; SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() }; #else SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point() }; SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point() }; #endif Common::EventManager *em = g_system->getEventManager(); Common::Event ev; bool found = em->pollEvent(ev); // Don't generate events for mouse movement while (found && ev.type == Common::EVENT_MOUSEMOVE) found = em->pollEvent(ev); // Save the mouse position // // We call getMousePos of the event manager here, since we also want to // store the mouse position in case of keyboard events, which do not feature // any mouse position information itself. // This should be safe, since the mouse position in the event manager should // only be updated when a mouse related event has been taken from the queue // via pollEvent. // We also adjust the position based on the scaling of the screen. Common::Point mousePos = em->getMousePos(); #if ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer(); Common::Point mousePosSci = mousePos; mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight)); noEvent.mousePosSci = input.mousePosSci = mousePosSci; } else { #endif g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x); #if ENABLE_SCI32 } #endif noEvent.mousePos = input.mousePos = mousePos; if (!found || ev.type == Common::EVENT_MOUSEMOVE) { int modifiers = em->getModifierState(); noEvent.modifiers = ((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) | ((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) | ((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0); return noEvent; } if (ev.type == Common::EVENT_QUIT) { input.type = SCI_EVENT_QUIT; return input; } int scummVMKeyFlags; switch (ev.type) { case Common::EVENT_KEYDOWN: case Common::EVENT_KEYUP: // Use keyboard modifiers directly in case this is a keyboard event scummVMKeyFlags = ev.kbd.flags; break; default: // Otherwise get them from EventManager scummVMKeyFlags = em->getModifierState(); break; } input.modifiers = ((scummVMKeyFlags & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) | ((scummVMKeyFlags & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) | ((scummVMKeyFlags & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0); // Caps lock and Scroll lock have been removed, cause we already handle upper // case keys and Scroll lock doesn't seem to be used anywhere //((ourModifiers & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) | //((ourModifiers & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) | // Handle mouse events for (int i = 0; i < ARRAYSIZE(mouseEventMappings); i++) { if (mouseEventMappings[i].commonType == ev.type) { input.type = mouseEventMappings[i].sciType; // Sierra passed keyboard modifiers for mouse events, too. // Sierra also set certain modifiers within their mouse interrupt handler // This whole thing was probably meant for people using a mouse, that only featured 1 button // So the user was able to press Ctrl and click the mouse button to create a right click. switch (ev.type) { case Common::EVENT_RBUTTONDOWN: // right button case Common::EVENT_RBUTTONUP: input.modifiers |= (SCI_KEYMOD_RSHIFT | SCI_KEYMOD_LSHIFT); // this value was hardcoded in the mouse interrupt handler break; case Common::EVENT_MBUTTONDOWN: // middle button case Common::EVENT_MBUTTONUP: input.modifiers |= SCI_KEYMOD_CTRL; // this value was hardcoded in the mouse interrupt handler break; default: break; } return input; } } // If we reached here, make sure that it's a keydown event if (ev.type != Common::EVENT_KEYDOWN) return noEvent; // Check for Control-Shift-D (debug console) if (ev.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_SHIFT) && ev.kbd.keycode == Common::KEYCODE_d) { // Open debug console Console *con = g_sci->getSciDebugger(); con->attach(); return noEvent; } // Process keyboard events bool numlockOn = (ev.kbd.flags & Common::KBD_NUM); Common::KeyCode scummVMKeycode = ev.kbd.keycode; input.character = ev.kbd.ascii; input.type = SCI_EVENT_KEYBOARD; if (scummVMKeycode >= Common::KEYCODE_KP0 && scummVMKeycode <= Common::KEYCODE_KP9) { if (!(scummVMKeyFlags & Common::KBD_NUM)) { // HACK: Num-Lock not enabled // We shouldn't get a valid ascii code in these cases. We fix it here, so that cursor keys // on the numpad work properly. input.character = 0; } } if ((input.character) && (input.character <= 0xFF)) { // Directly accept most common keys without conversion if ((input.character >= 0x80) && (input.character <= 0xFF)) { // If there is no extended font, we will just clear the // current event. // Sierra SCI actually accepted those characters, but // didn't display them inside text edit controls because // the characters were missing inside the font(s). // We filter them out for non-multilingual games because // of that. if (!_fontIsExtended) return noEvent; // Convert 8859-1 characters to DOS (cp850/437) for // multilingual SCI01 games input.character = codePageMap88591ToDOS[input.character & 0x7f]; } if (scummVMKeycode == Common::KEYCODE_TAB) { input.character = SCI_KEY_TAB; if (scummVMKeyFlags & Common::KBD_SHIFT) input.character = SCI_KEY_SHIFT_TAB; } if (scummVMKeycode == Common::KEYCODE_DELETE) input.character = SCI_KEY_DELETE; } else if ((scummVMKeycode >= Common::KEYCODE_F1) && scummVMKeycode <= Common::KEYCODE_F10) { // SCI_K_F1 == 59 << 8 // SCI_K_SHIFT_F1 == 84 << 8 if (!(scummVMKeyFlags & Common::KBD_SHIFT)) input.character = SCI_KEY_F1 + ((scummVMKeycode - Common::KEYCODE_F1)<<8); else input.character = SCI_KEY_SHIFT_F1 + ((scummVMKeycode - Common::KEYCODE_F1)<<8); } else { // Special keys that need conversion for (int i = 0; i < ARRAYSIZE(keyMappings); i++) { if (keyMappings[i].scummVMKey == scummVMKeycode) { input.character = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff; break; } } } // When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give // us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway // we support the other case as well if ((scummVMKeyFlags & Common::KBD_ALT) && input.character > 0 && input.character < 27) input.character += 96; // 0x01 -> 'a' // Scancodify if appropriate if (scummVMKeyFlags & Common::KBD_ALT) input.character = altify(input.character); if (getSciVersion() <= SCI_VERSION_1_MIDDLE && (scummVMKeyFlags & Common::KBD_CTRL) && input.character > 0 && input.character < 27) input.character += 96; // 0x01 -> 'a' #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2 && (scummVMKeyFlags & Common::KBD_CTRL) && input.character == 'c') { input.character = SCI_KEY_ETX; } #endif // If no actual key was pressed (e.g. if only a modifier key was pressed), // ignore the event if (!input.character) return noEvent; return input; }