/** * \brief This function is called by the game when a low-level event occurs. * \param event An input event. */ void GameCommands::notify_input(const InputEvent& event) { // If no game command is being customized, we look for a binding // for this input event and we ignore the event if no binding is found. // If a command is being customized, we consider instead this event as // the new binding for this game command. if (event.is_keyboard_key_pressed()) { keyboard_key_pressed(event.get_keyboard_key()); } else if (event.is_keyboard_key_released()) { keyboard_key_released(event.get_keyboard_key()); } else if (event.is_joypad_button_pressed()) { joypad_button_pressed(event.get_joypad_button()); } else if (event.is_joypad_button_released()) { joypad_button_released(event.get_joypad_button()); } else if (event.is_joypad_axis_moved()) { joypad_axis_moved(event.get_joypad_axis(), event.get_joypad_axis_state()); } else if (event.is_joypad_hat_moved()) { joypad_hat_moved(event.get_joypad_hat(), event.get_joypad_hat_direction()); } }
void keyboard_routine() { unsigned char key = inb(PORT_PS2_DATA); if ((key & 0x80) == 0) { // Show character on screen char c = char_map[key & 0x7f]; printc_xy(0, 0, (c != '\0' ? c : 'C')); // Send keypress to tasks if needed keyboard_key_pressed(c); } }
int kbd_handle_keydown(DWORD virtual_key, DWORD key_data) { int kcode = (key_data >> 16) & 0xff; int repeated = key_data & 0x40000000 ? 1 : 0; if (virtual_key == 0xff) return 0; /* Translate Extended scancodes */ if (key_data & (1 << 24)) { kcode = _kbd_extended_key_tab[kcode]; } if ( ! repeated ) { keyboard_key_pressed((signed long)kcode); } return 0; }
static gboolean kbd_event_handler(GtkWidget *w, GdkEvent *report, gpointer gp) { gint key; key = report->key.keyval; switch (report->type) { case GDK_KEY_PRESS: #ifdef DEBUG_KBD log_debug("KeyPress`%d'.", key); #endif keyboard_key_pressed((signed long)key); return TRUE; case GDK_KEY_RELEASE: #ifdef DEBUG_KBD log_debug("KeyRelese`%d'.", key); #endif if (key == KEYSYM_Shift_L || key == KEYSYM_Shift_R || key == KEYSYM_ISO_Level3_Shift || /* the following checks are an ugly workaround for bug #549 for some reasond gdk returns different keycodes for press and release events of the shift keys. any explanation would be helpful */ key == KEYSYM_Shift_Lrel || key == KEYSYM_Shift_Rrel) { keyboard_key_clear(); } keyboard_key_released(key); break; case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: case GDK_FOCUS_CHANGE: keyboard_key_clear(); break; default: break; } /* switch */ return FALSE; }
ui_menu_action_t sdlkbd_press(SDLKey key, SDLMod mod) { ui_menu_action_t i, retval = MENU_ACTION_NONE; ui_menu_entry_t *hotkey_action = NULL; #ifdef SDL_DEBUG fprintf(stderr, "%s: %i (%s),%i\n", __func__, key, SDL_GetKeyName(key), mod); #endif if (sdl_menu_state || (sdl_vkbd_state & SDL_VKBD_ACTIVE)) { if (key != SDLK_UNKNOWN) { for (i = MENU_ACTION_UP; i < MENU_ACTION_NUM; ++i) { if (sdl_ui_menukeys[i] == (int)key) { retval = i; break; } } if ((int)(key) == sdl_ui_menukeys[0]) { retval = MENU_ACTION_EXIT; } } return retval; } if ((int)(key) == sdl_ui_menukeys[0]) { sdl_ui_activate(); return retval; } if ((hotkey_action = sdlkbd_get_hotkey(key, mod)) != NULL) { sdl_ui_hotkey(hotkey_action); return retval; } keyboard_key_pressed((unsigned long)key); return retval; }
void gp2x_poll_usb_input(void) { static int stats_button; static int prefs_button; static int vkeyb_button; static int joy_time = 0; static unsigned int a_held = 0; static unsigned int x_held = 0; unsigned int i; unsigned int j; unsigned int joy_state = gp2x_joystick_read(0); //usb joysticks if (gp2x_usbjoys > 0) { joy_state = gp2x_joystick_read(1); j = joystick_value[cur_portusb1]; if (joy_state & GP2X_UP) { j |= 0x01; } else { j &= ~0x01; } if (joy_state & GP2X_DOWN) { j |= 0x02; } else { j &= ~0x02; } if (joy_state & GP2X_LEFT) { j |= 0x04; } else { j &= ~0x04; } if (joy_state & GP2X_RIGHT) { j |= 0x08; } else { j &= ~0x08; } if (joy_state & (GP2X_B | GP2X_PUSH)) { j |= 0x10; } else { j &= ~0x10; } joystick_value[cur_portusb1] = j; if (gp2x_usbjoys > 1) { joy_state = gp2x_joystick_read(2); j = joystick_value[cur_portusb2]; if (joy_state & GP2X_UP) { j |= 0x01; } else { j &= ~0x01; } if (joy_state & GP2X_DOWN) { j |= 0x02; } else { j &= ~0x02; } if (joy_state & GP2X_LEFT) { j |= 0x04; } else { j &= ~0x04; } if (joy_state & GP2X_RIGHT) { j |= 0x08; } else { j &= ~0x08; } if (joy_state & (GP2X_B | GP2X_PUSH)) { j |= 0x10; } else { j &= ~0x10; } joystick_value[cur_portusb2]=j; } } //usb keyboard for (i = 0; i < gp2x_keyboard_readext(); ++i) { int keycode = keybuffer[i]; if (keycode & 0x80) { keycode &= 0x7f; // Remove release bit keyboard_key_released((signed long)keycode); } else { keyboard_key_pressed((signed long)keycode); } } }
int joystick(void) { static bool key_cursorup = false; static bool key_cursordown = false; static bool key_cursorleft = false; static bool key_cursorright = false; static bool warp_mode=false; // osk_active_bufferlen == The OSK is entering characters, don't interrupt it. // autostart_in_progress() == // Autostart is running. Don't allow the joystick to interrupt. // In particular this can break the actual autostart script that tests the basic prompt due to interference if (osk_active_bufferlen || autostart_in_progress()) { return 0; } uint8_t pads_connected = CellInput->NumberPadsConnected(); for (uint8_t i = 0; i < pads_connected; ++i) { int value = 0; // Do PS3 pads CellInput->UpdateDevice(i); // Set the joystick values if (CellInput->IsButtonPressed(i,CTRL_LEFT) | CellInput->IsAnalogPressedLeft(i,CTRL_LSTICK)) value |= 4; if (CellInput->IsButtonPressed(i,CTRL_RIGHT) | CellInput->IsAnalogPressedRight(i,CTRL_LSTICK)) value |= 8; if (CellInput->IsButtonPressed(i,CTRL_UP) | CellInput->IsAnalogPressedUp(i,CTRL_LSTICK)) value |= 1; if (CellInput->IsButtonPressed(i,CTRL_DOWN) | CellInput->IsAnalogPressedDown(i,CTRL_LSTICK)) value |= 2; // Process re-definable controls process_button (i, CTRL_CROSS, &value); process_button (i, CTRL_CIRCLE, &value); process_button (i, CTRL_SQUARE, &value); process_button (i, CTRL_TRIANGLE, &value); process_button (i, CTRL_L1, &value); process_button (i, CTRL_L2, &value); process_button (i, CTRL_R1, &value); process_button (i, CTRL_R2, &value); // Emulator cursor keys if (CellInput->IsAnalogPressedUp(i,CTRL_RSTICK)) { if (!key_cursorup) { keyboard_key_pressed((signed long) 32850); // Cursor Up key pressed key_cursorup = true; } } else { if (key_cursorup) { keyboard_key_released((signed long) 32850); // Cursor Up key released key_cursorup = false; } } if (CellInput->IsAnalogPressedDown(i,CTRL_RSTICK)) { if (!key_cursordown) { keyboard_key_pressed((signed long) 32849); // Cursor Down key pressed key_cursordown = true; } } else { if (key_cursordown) { keyboard_key_released((signed long) 32849); // Cursor Down key released key_cursordown = false; } } if (CellInput->IsAnalogPressedLeft(i,CTRL_RSTICK)) { if (!key_cursorleft) { keyboard_key_pressed((signed long) 32848); // Cursor Left key pressed key_cursorleft = true; } } else { if (key_cursorleft) { keyboard_key_released((signed long) 32848); // Cursor Left key released key_cursorleft = false; } } if (CellInput->IsAnalogPressedRight(i,CTRL_RSTICK)) { if (!key_cursorright) { keyboard_key_pressed((signed long) 32847); // Cursor Right key pressed key_cursorright = true; } } else { if (key_cursorright) { keyboard_key_released((signed long) 32847); // Cursor Right key released key_cursorright = false; } } if ((CellInput->IsButtonPressed(0,CTRL_R2) && CellInput->IsButtonPressed(0,CTRL_L2)) || (CellInput->IsButtonPressed(1,CTRL_R2) && CellInput->IsButtonPressed(1,CTRL_L2))) { if (!warp_mode) { // Disable sound (makes warp mode infinitely faster) resources_set_int("Sound", 0); // Enable Warp Mode resources_set_int("WarpMode", 1); warp_mode=true; } } else { if (warp_mode) { resources_set_int("WarpMode", 0); resources_set_int("Sound", 1); warp_mode=false; } } if (CellInput->IsButtonPressed(i,CTRL_L1) && CellInput->IsButtonPressed(i,CTRL_R1) && CellInput->IsButtonPressed(i,CTRL_L2) && CellInput->IsButtonPressed(i,CTRL_R2) ) machine_trigger_reset(MACHINE_RESET_MODE_HARD); /* // Swap joysticks if (CellInput->WasButtonPressed(i,CTRL_SELECT)) { // Do nothing } // Required because keyloop kills us if (CellInput->WasButtonReleased(i,CTRL_SELECT)) { if (pads_connected == 1) // Only allow us to swap joystick ports if there is only one controller // Otherwise, multiplayer madness and much punching will ensue. joyswap=!joyswap; } */ if (CellInput->WasButtonPressed(i,CTRL_SELECT)) InGameMenuLoop(); if(CellInput->WasButtonPressed(i,CTRL_START)) { menu(MODE_MENU); // Stop the clock (effectively, tells the emulator we were paused) vsync_suspend_speed_eval(); // Apply any changes as necessary. } if(CellInput->WasButtonPressed(i,CTRL_L3)) { // Vice OSK menu(MODE_OSK); // Stop the clock (effectively, tells the emulator we were paused) vsync_suspend_speed_eval(); // Apply any changes as necessary. } if(CellInput->WasButtonPressed(i,CTRL_R3)) { osk->Start(L"Characters entered here will be relayed to the emulator ", L""); #ifdef CELL_DEBUG printf("OSK started\n"); #endif // Just in case. This ensures we check to see if the screen has updated, and if not.. force one // The OSK fails to draw if the screen doesn't update. } cellSysutilCheckCallback(); if (sysutil_drawing) sysutil_callback_redraw(); ui_callback(); // pad 0 becomes port 2 // pad 1 becomes port 1 if (joyswap) joystick_set_value_absolute( ((i+1) % 2 ) + 1, value); else joystick_set_value_absolute(i+1, value); // pad 0 becomes port 1 // pad 1 becomes port 2 } return 0; }
void process_button (int pad_id, int pad_button, int *value) { int function; // mapped controller funciton int keycode; // keycode associated with that controller function // represents mapped button state for each pad controller static bool button_state[2][MAX_JOYMAP_CONTROLS]; int map_id=0; switch (pad_button) { case CTRL_CROSS: map_id = CROSS; break; case CTRL_CIRCLE: map_id = CIRCLE; break; case CTRL_SQUARE: map_id = SQUARE; break; case CTRL_TRIANGLE: map_id = TRIANGLE; break; case CTRL_L1: map_id = L1; break; case CTRL_L2: map_id = L2; break; case CTRL_R1: map_id = R1; break; case CTRL_R2: map_id = R2; break; default: return; break; } if (CellInput->IsButtonPressed(pad_id,pad_button)) { function = get_joymap_value (pad_id,map_id); if (function == JOYMAP_FIRE) *value |= 16; else if (function == JOYMAP_UP) *value |= 1; else if (function == FUNC_IN_GAME_MENU) InGameMenuLoop(); else { if (!button_state[pad_id][map_id]) { keycode = get_joymap_keycode (function); if (keycode != 0) { button_state[pad_id][map_id] = true; keyboard_key_pressed(keycode); } } } } else { if (button_state[pad_id][map_id]) { keycode = get_joymap_keycode (get_joymap_value(pad_id, map_id)); if (keycode != 0) { button_state[pad_id][map_id] = false; keyboard_key_released(keycode); } } } }
/* unused ? */ void ui_dispatch_next_event(void) { #ifdef ANDROID_COMPILE struct locnet_al_event event; if (Android_PollEvent(&event)) { #else SDL_Event e; if (SDL_PollEvent(&e)) { ui_handle_misc_sdl_event(e); #endif } else { /* Add a small delay to not hog the host CPU when remote monitor is being used. */ SDL_Delay(10); } } #endif /* Main event handler */ ui_menu_action_t ui_dispatch_events(void) { SDL_Event e; ui_menu_action_t retval = MENU_ACTION_NONE; #ifdef ANDROID_COMPILE struct locnet_al_event event1; if (loader_showinfo) { int value = loader_showinfo; loader_showinfo = 0; loader_set_statusbar((value == 1) ? 1 : 0); } if (loader_true_drive) { int value = loader_true_drive; loader_true_drive = 0; loader_set_drive_true_emulation((value == 1) ? 1 : 0); } if (loader_turbo) { int value = loader_turbo; loader_turbo = 0; loader_set_warpmode((value == 1) ? 1 : 0); } if (loadf->frameskip) { int value = loadf->frameskip; loadf->frameskip = 0; resources_set_int("RefreshRate", ((value > 0) && (value <= 10)) ? (value + 1) : 1); } if (loadf->abort) { loadf->abort = 0; ui_pause_emulation(1); ui_sdl_quit(); ui_pause_emulation(0); return MENU_ACTION_NONE; } else if (loader_loadstate) { loader_loadstate = 0; loader_load_snapshot(savestate_filename); ui_pause_emulation(0); return MENU_ACTION_NONE; } else if (loader_savestate) { loader_savestate = 0; loader_save_snapshot(savestate_filename); ui_pause_emulation(0); return MENU_ACTION_NONE; } int stopPoll = 0; while ((!stopPoll) && Android_PollEvent(&event1)) { struct locnet_al_event *event = &event1; switch (event->eventType) { case SDL_MOUSEMOTION: { //locnet, 2011-06-16, detect auto calibrate if ((event->x == -2048) && (event->y == -2048)) { down_x = -1; down_y = -1; oldx = 0; oldy = 0; stopPoll = 1; //locnet, 2011-07-01, detect pure relative move } else if ((event->down_x == -1024) && (event->down_y == -1024)) { down_x = 0; down_y = 0; oldx = 0; oldy = 0; } else if ((down_x != event->down_x) || (down_y != event->down_y)) { down_x = event->down_x; down_y = event->down_y; oldx = down_x; oldy = down_y; } mouse_move((int)(event->x - oldx), (int)(event->y - oldy)); oldx = event->x; oldy = event->y; } break; case SDL_MOUSEBUTTONDOWN: { if ((event->down_x >= 0) && (event->down_y >= 0)) { mouse_x = 640 * event->down_x / 1000.0f - 64; mouse_y = 400 * (1000 - event->down_y) / 1000.0f - 200; } if (event->keycode >= 0) { mouse_button((int)(event->keycode) ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT, 1); } stopPoll = 1; } break; case SDL_MOUSEBUTTONUP: { if (event->keycode >= 0) { mouse_button((int)(event->keycode) ? SDL_BUTTON_RIGHT : SDL_BUTTON_LEFT, 0); } stopPoll = 1; } break; case SDL_JOYAXISMOTION: { float x = event->x / 256.0f; float y = event->y / 256.0f; int left = 0, top = 0, right = 0, bot = 0; int value; if (y < -DEAD_ZONE) { top = 1; } if (y > DEAD_ZONE) { bot = 1; } if (x < -DEAD_ZONE) { left = 1; } if (x > DEAD_ZONE) { right = 1; } value = 0; if (left) { value |= 4; } if (right) { value |= 8; } if (top) { value |= 1; } if (bot) { value |= 2; } retval = sdljoy_axis_event(0, 0, event->x / 256.0f * 32767); ui_menu_action_t retval2 = sdljoy_axis_event(0, 1, event->y / 256.0f * 32767); if (retval == MENU_ACTION_NONE) { retval = retval2; } old_joy_direction = value; stopPoll = 1; } break; case SDL_JOYBUTTONDOWN: { retval = sdljoy_button_event(0, event->keycode, 1); //2011-09-20, buffer overflow when autofire if stopPoll if (!Android_HasRepeatEvent(SDL_JOYBUTTONDOWN, event->keycode)) { stopPoll = 1; } } break; case SDL_JOYBUTTONUP: { retval = sdljoy_button_event(0, event->keycode, 0); //2011-09-20, buffer overflow when autofire if stopPoll if (!Android_HasRepeatEvent(SDL_JOYBUTTONUP, event->keycode)) { stopPoll = 1; } } break; case SDL_KEYUP: case SDL_KEYDOWN: { static int ctrl_down = 0; static int alt_down = 0; static int shift_down = 0; int down = (event->eventType == SDL_KEYDOWN); unsigned long modifier = event->modifier; int ctrl = ((modifier & KEYBOARD_CTRL_FLAG) != 0); int alt = ((modifier & KEYBOARD_ALT_FLAG) != 0); int shift = ((modifier & KEYBOARD_SHIFT_FLAG) != 0); unsigned long kcode = (unsigned long)event->keycode; int kmod = 0; if (ctrl) { kmod |= KMOD_LCTRL; } if (alt) { kmod |= KMOD_LALT; } if (shift) { kmod |= KMOD_LSHIFT; } if (down) { if (ctrl || (kcode == SDLK_TAB)) { if (!ctrl_down) { keyboard_key_pressed((unsigned long)SDLK_TAB); } ctrl_down++; } if (alt || (kcode == SDLK_LCTRL)) { if (!alt_down) { keyboard_key_pressed((unsigned long)SDLK_LCTRL); } alt_down++; } if (shift || (kcode == SDLK_LSHIFT)) { if (!shift_down) { keyboard_key_pressed((unsigned long)SDLK_LSHIFT); } shift_down++; } retval = sdlkbd_press(kcode, 0); } else { retval = sdlkbd_release(kcode, 0); if (ctrl || (kcode == SDLK_TAB)) { if (kcode == SDLK_TAB) { ctrl_down = 0; } if (ctrl_down) { ctrl_down--; } if (!ctrl_down) { keyboard_key_released((unsigned long)SDLK_TAB); } } if (alt || (kcode == SDLK_LCTRL)) { if (kcode == SDLK_LCTRL) { alt_down = 0; } if (alt_down) { alt_down--; } if (!alt_down) { keyboard_key_released((unsigned long)SDLK_LCTRL); } } if (shift || (kcode == SDLK_LSHIFT)) { if (kcode == SDLK_LSHIFT) { shift_down = 0; } if (shift_down) { shift_down--; } if (!shift_down) { keyboard_key_released((unsigned long)SDLK_LSHIFT); } } } stopPoll = 1; } break; } } #else while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_KEYDOWN: retval = sdlkbd_press(e.key.keysym.sym, e.key.keysym.mod); break; case SDL_KEYUP: retval = sdlkbd_release(e.key.keysym.sym, e.key.keysym.mod); break; #ifdef HAVE_SDL_NUMJOYSTICKS case SDL_JOYAXISMOTION: retval = sdljoy_axis_event(e.jaxis.which, e.jaxis.axis, e.jaxis.value); break; case SDL_JOYBUTTONDOWN: retval = sdljoy_button_event(e.jbutton.which, e.jbutton.button, 1); break; case SDL_JOYBUTTONUP: retval = sdljoy_button_event(e.jbutton.which, e.jbutton.button, 0); break; case SDL_JOYHATMOTION: retval = sdljoy_hat_event(e.jhat.which, e.jhat.hat, e.jhat.value); break; #endif case SDL_MOUSEMOTION: if (_mouse_enabled) { mouse_move((int)(e.motion.xrel), (int)(e.motion.yrel)); } break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: if (_mouse_enabled) { mouse_button((int)(e.button.button), (e.button.state == SDL_PRESSED)); } break; default: /* SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE); */ ui_handle_misc_sdl_event(e); /* SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE); */ break; } /* When using the menu or vkbd, pass every meaningful event to the caller */ if (((sdl_menu_state) || (sdl_vkbd_state & SDL_VKBD_ACTIVE)) && (retval != MENU_ACTION_NONE) && (retval != MENU_ACTION_NONE_RELEASE)) { break; } } #endif return retval; }
static void my_kbd_interrupt_handler(void) { static int extended = 0; /* Extended key count. */ static int skip_count = 0; unsigned int kcode; kcode = inportb(0x60); if (skip_count > 0) { skip_count--; outportb(0x20, 0x20); return; } else if (kcode == 0xe0) { /* Extended key: at the next interrupt we'll get its extended keycode or 0xe0 again. */ extended++; outportb(0x20, 0x20); return; } else if (kcode == 0xe1) { /* Damn Pause key. It sends 0xe1 0x1d 0x52 0xe1 0x9d 0xd2. This is awesome, but at least we know it's the only sequence starting by 0xe1, so we can just skip the next 5 codes. Btw, there is no release code. */ skip_count = 5; kcode = K_PAUSE; } if (!(kcode & 0x80)) { /* Key pressed. */ /* Derive the extended keycode. */ if (extended == 1) { kcode = _kbd_extended_key_tab[kcode]; } /* Handle modifiers. */ switch (kcode) { case K_LEFTCTRL: modifiers.left_ctrl = 1; break; case K_RIGHTCTRL: modifiers.right_ctrl = 1; break; case K_LEFTSHIFT: modifiers.left_shift = 1; break; case K_RIGHTSHIFT: modifiers.right_shift = 1; break; case K_LEFTALT: modifiers.left_alt = 1; break; case K_RIGHTALT: modifiers.right_alt = 1; break; } switch (kcode) { case K_ESC: /* Menu */ queue_command(KCMD_MENU, (kbd_command_data_t)0); break; case K_SCROLLOCK: /* Warp mode on/off */ queue_command(KCMD_TOGGLE_WARP, (kbd_command_data_t)0); break; /* Fall through */ default: if (modifiers.left_alt && modifiers.left_ctrl) { switch (kcode) { case K_F12: /* Ctrl-Alt-F12 does a hard reset. */ queue_command(KCMD_HARD_RESET, (kbd_command_data_t)0); break; case K_F4: /* Ctrl-Alt-F4 is RECORD on the datasette. */ queue_command(KCMD_DATASETTE_RECORD, (kbd_command_data_t)0); break; case K_F5: /* Ctrl-Alt-F5 is PLAY on the datasette. */ queue_command(KCMD_DATASETTE_START, (kbd_command_data_t)0); break; case K_F6: /* Ctrl-Alt-F6 is REWIND on the datasette. */ queue_command(KCMD_DATASETTE_REWIND, (kbd_command_data_t)0); break; case K_F7: /* Ctrl-Alt-F7 is FF on the datasette. */ queue_command(KCMD_DATASETTE_FORWARD, (kbd_command_data_t)0); break; case K_F8: /* Ctrl-Alt-F8 is STOP on the datasette. */ queue_command(KCMD_DATASETTE_STOP, (kbd_command_data_t)0); break; } } else if (modifiers.left_alt || modifiers.right_alt) { /* Handle Alt-... hotkeys. */ switch (kcode) { case K_F12: /* Alt-F12 does a reset. */ queue_command(KCMD_RESET, (kbd_command_data_t)0); break; case K_F1: /* Alt-F1 Next image in flip list. */ queue_command(KCMD_FLIP_NEXT, (kbd_command_data_t)0); break; case K_F2: /* Alt-F2 Previous image in flip list. */ queue_command(KCMD_FLIP_PREVIOUS, (kbd_command_data_t)0); break; case K_F3: /* Alt-F3 Add image to flip list. */ queue_command(KCMD_FLIP_ADD, (kbd_command_data_t)0); break; case K_F4: /* Alt-F4 remove image from flip list. */ queue_command(KCMD_FLIP_REMOVE, (kbd_command_data_t)0); break; case K_F5: /* Alt-F5 toggles statusbar. */ queue_command(KCMD_TOGGLE_STATUSBAR, (kbd_command_data_t)0); break; case K_PAUSE: /* Alt-Pause enables cartridge freezing. */ queue_command(KCMD_FREEZE, (kbd_command_data_t)0); break; default: /* Alt-{letter,number} enters the main menu. */ if (isalnum((int)kcode_to_ascii(kcode))) { queue_command(KCMD_MENU, (kbd_command_data_t)kcode_to_ascii(kcode)); } } } else { /* "Normal" key. */ keyboard_key_pressed((signed long)kcode); } } } else { /* Key released. */ /* Remove release bit. */ kcode &= 0x7f; /* Derive the extended keycode. */ if (extended == 1) { kcode = _kbd_extended_key_tab[kcode]; } /* Handle modifiers. */ switch (kcode) { case K_LEFTCTRL: modifiers.left_ctrl = 0; break; case K_RIGHTCTRL: modifiers.right_ctrl = 0; break; case K_LEFTSHIFT: modifiers.left_shift = 0; break; case K_RIGHTSHIFT: modifiers.right_shift = 0; break; case K_LEFTALT: modifiers.left_alt = 0; break; case K_RIGHTALT: modifiers.right_alt = 0; break; } if (!modifiers.left_alt && !modifiers.right_alt) { /* "Normal" key. */ keyboard_key_released((signed long)kcode); } } extended = 0; outportb(0x20, 0x20); }